(25+4/25+4)复健-KMP/EKMP/manache/Trie
(29/29) 3.23已完成
1.KMP
int Next[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,char* y){
int lenx=strlen(x);
int leny=strlen(y);
int pre=,suf=,ans=;
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}
模板
模板写法及变式(待更新)
基本形
其中,next数组的0号位为缺省值-1,其余位为正常位,第len位为保留位(用于处理全部匹配情况)。
next[i]存储的是对应前i-1位的最大公共前后缀长度。
一般算法理论中讨论的前后缀都是真前后缀,即不包含自身的的前后缀,为运用方便,以后统一如此编程。
next[i]=k的意义是模式串0~k-1位与i~i+k-1位相等,方便主匹配指针(指向结尾)直接通过递归方式快速滚动(j->next[j])
所以能辨别的公共词缀最小长度为2,单字不相同与单字相同无法辨别。
这是因为next数组是经过方便指针快速滚动而改造的,默认意义下的kmp算法的核心是主指针的失配而不是指针的匹配。
HDU 1711(数字序列单模式串匹配)
要求输出第一个成功匹配的位置,匹配成功直接return就好了
模板题
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 10010
int a[maxn],b[maxm],Next[maxm];
int n,m,T;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=-;
//Next[0]=0,Next[1]=0;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {if(ans==-) ans=suf-m+; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
cin>>T;
FOR(i,,T){
cin>>n>>m;
FOR(i,,n)
a[i]=(int) read();
FOR(i,,m)
b[i]=(int) read();
doit();
kmp();
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
HDU-1686(单模式串匹配)
要求输出匹配次数(可重叠)
模板题,匹配成功直接做失配处理
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 10010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++;; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
FOR(i,,t){
scanf("%s",b+); m=strlen(b+);
scanf("%s",a+); n=strlen(a+);
doit();
kmp();
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
HDU 2087(单模式串匹配)
要求输出匹配次数(不可重叠)
模板题,以前写的是保留上次匹配的结果以检验是否可能重叠。现在看来直接将副指针归零即可
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 10010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=,spre=;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m&&suf>=spre+m) {ans++; spre=suf; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
while(true){
scanf("%s",a+); if(a[]=='#') break; n=strlen(a+);
scanf("%s",b+); m=strlen(b+);
doit();
kmp();
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
HDU 1711(单模式串匹配)
要求输出第一个成功匹配的位置
模板题,练手
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 10010
int a[maxn],b[maxm],Next[maxm];
int n,m,T;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=-;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {if(ans==-) ans=suf-m+; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
cin>>T;
FOR(i,,T){
cin>>n>>m;
FOR(i,,n)
a[i]=(int) read();
FOR(i,,m)
b[i]=(int) read();
doit();
kmp();
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
POJ 2752
求最大公共前后缀
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 1000010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t,len;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
//Next[0]=0,Next[1]=0;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
stack<int> ans;
while(scanf("%s",b+)!=EOF){
m=strlen(b+);
doit();
while(!ans.empty()) ans.pop();
ans.push(m);
while(Next[m]!=) ans.push(m=Next[m]);
printf("%d",ans.top());ans.pop();
while(!ans.empty()){printf(" %d",ans.top());;ans.pop();}
cout<<endl;
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
POJ 3080
确定多个串的最大公共子串,穷举答案即可(就用第一个字符串)
穷举答案也是字符串题常见操作了,固定起点的话记得一失配就break掉
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 70
int Next[maxn];
int lens[maxn];
char s[maxn][maxn];
char xx[maxn];
void prekmp(char x[],int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(int lenx,char *x,int leny,char *y){
//int lenx=strlen(x);
//int leny=strlen(y);
int pre=,suf=,ans=;//FOR(i,0,lenx) cout<<x[i]<<"**";
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int T,n,cnt,flag,jj=;
scanf("%d",&T); while(T--){
scanf("%d",&n);
FOR(i,,n){
scanf("%s",s[i]);
lens[i]=strlen(s[i]);
}
int len0=strlen(s[]);
int maxlen=-,leni=,lenj=; FOR(i,,len0-){
cnt=-;
xx[++cnt]=s[][i];
FOR(j,i+,len0){
xx[++cnt]=s[][j];
flag=true;
jj=j;
FOR(k,,n) if(!kmp(cnt+,xx,lens[k],s[k])) {flag=false;break;}
if(!flag) {jj--;break;}
}
if(jj-i>){
if(maxlen<jj-i+) {maxlen=jj-i+;leni=i;lenj=jj;}
else if(maxlen==jj-i+){
FOR(p,,jj-i+) if(s[][leni+p]>s[][i+p]){maxlen=jj-i+;leni=i;lenj=jj;break;}
}
}
}
if(maxlen!=-) FOR(p,leni,lenj+) printf("%c",s[][p]);
else printf("no significant commonalities");
if(T!=) printf("\n");
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
hdu 2594
求S1的前缀和S2的后缀的最大匹配
建立新字符串S=S1+S2 跑个next,然后递归next[lens1+lens2],找到第一个小于lens1的next[]
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 200010
#define maxm 200010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t,len;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
//Next[0]=0,Next[1]=0;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
//stack<int> ans;
while(scanf("%s%s",b+,a+)!=EOF){
m=strlen(b+);
n=strlen(a+);
FOR(i,,n)
b[i+m]=a[i];
int lm=m;
m+=n;//cout<<n;
doit();
if(lm==) {if(b[]==b[m]) printf("%c 1\n",b[]); else printf("0\n"); }
else if(Next[m]){
while(Next[m]>lm||Next[m]>n) m=Next[m];
FOR(i,,Next[m])
printf("%c",b[i]);
printf(" %d\n",Next[m]);
}
else printf("0\n");
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
hdu 3336
给出字符串S, 输出S所有前缀的出现次数之和
显然的,有s[0~k-1]的所有前缀的出现次数之和=s[0~next[k]]的所有前缀的出现次数之和+s[0~next[k]]这个最大的公共前后缀
为了省事直接push型dp。
不显然的,这题应该有更深的理解,remain update
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 200010
int t,n;
char x[maxn];
int Next[maxn],f[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<=len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,int lenx,char* y,int leny){
//int lenx=strlen(x);
//int leny=strlen(y);
int pre=,suf=,ans=;
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}int dp[maxn];
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
FOR(i,,t){
int ans;
scanf("%d",&n);
scanf("%s",x);
memset(Next,,sizeof(Next));
memset(dp,,sizeof(dp));
prekmp(x,n);
dp[]=; ans=;
FOR(j,,n+) {
dp[j]=(dp[Next[j]]+)%;
ans+=dp[j];
ans=ans%;
}
printf("%d\n",ans);
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
hdu 1238
n个串的最大公共子串,这里的子串要求其本身匹配或者其倒转串匹配
枚举答案题的加强版,依然是善用break
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 210
char s[][maxn];
char xx[maxn];
int len[maxn];
int t,ans,cnt,flag,leni,lenj;
int Next[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,int lenx,char* y,int leny){
//int lenx=strlen(x);
//int leny=strlen(y);
int pre=,suf=,ans=;
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
return ans;
}
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int pp;
scanf("%d",&pp);
FOR(ppp,,pp){
scanf("%d",&t);
ans=-;
FOR(i,,t){
cin>>s[i];len[i]=strlen(s[i]);}
FOR(i,,len[]){
cnt=;
flag=true;
FOR(j,i,len[]){
xx[cnt++]=s[][j];
FOR(k,,t)
if(!kmp(xx,cnt,s[k],len[k])){
reverse(xx,xx+cnt);
if(!kmp(xx,cnt,s[k],len[k]))
{reverse(xx,xx+cnt);flag=false;break;}
reverse(xx,xx+cnt);
}
if(flag) ans=max(ans,cnt-);
}
}
printf("%d\n",ans+);
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
反转函数reverse
虽然这玩意poj是ban掉的。。。。用法是reverse(x.begin(),x.end())。常用且善用!!!!
hdu 2328
n个串的最大公共子串,多测,数据鬼畜,愣是卡掉了我的代码,至今不知道自己怎么错的。。。
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
const int N = , M = ;
char s[M][N], p[N], ans[N];
int m, mx, t, k, ne[N];
void getNext() {
ne[] = ;
for (int i = , j = ; i <= m; i++) {
while (j && p[i] != p[j + ]) j = ne[j];
if (p[i] == p[j + ]) j++;
ne[i] = j;
}
}
bool kmp(int k) {
int n = strlen(s[k] + );
getNext();
for (int i = , j = ; i <= n; i++) {
while (j && s[k][i] != p[j + ]) j = ne[j];
if (s[k][i] == p[j + ]) j++;
if (j == m) return true;//匹配成功
}
return false;
}
bool ok() {
for (int i = ; i <= k; i++) {
if (!kmp(i)) return false;
}
return true;
}
int main() {
while (scanf("%d", &k), k) {
for (int i = ; i <= k; i++) scanf("%s", s[i] + );
//枚举所有字串
int n = strlen(s[] + ); mx = ;
for (int i = ; i <= n; i++) {
for (int j = i; j <= n; j++) {
for (int h = i; h <= j; h++) p[h - i + ] = s[][h];
m = j - i + ; p[m + ] = '\0';
if (ok()) {
if (m > mx) { mx = m; memcpy(ans + , p + , sizeof(p));}
else if(m == mx && strcmp(ans + , p + ) > ) memcpy(ans + , p + , sizeof(p));
}
}
}
if (!mx) printf("IDENTITY LOST\n");
else printf("%s\n", ans + );
}
return ;
}
ac代码
fzu 1901
求所有公共前后缀,滚一边就好了
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
int n;
char x[maxn];
int Next[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,char* y){
int lenx=strlen(x);
int leny=strlen(y);
int pre=,suf=,ans=;
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&n);
FOR(i,,n+){
scanf("%s",x);
int len=strlen(x);
prekmp(x,len);
printf("Case #%d: ",i);
queue<int> xx;
for(int j=len;j;j=Next[j]){
xx.push(len-Next[j]);
}
int ans=SZ(xx);
printf("%d\n",ans);
FOR(j,,ans-){
printf("%d ",xx.front());
xx.pop();
}
printf("%d\n",xx.front());xx.pop();
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
循环节定理(保留位)
如果有len%=(len-next[len])==0,则字符串由循环节构成,最小循环节长度为len-next[len],主指针失配时每次向前固定跳len-next[len]。
需要明白的是,该定理的成立是依赖于指针快速滚动的,只有当条件成立时,才会出现字符串由循环节构成。
在一般的情况下,next数组时严格递增且满足等差数列性质,除了最后一次外每次向前滚动的长度相等,只有当每次向前滚动的长度大于目前长度时才会出现滚动长度的变化。
而且不难证明,这样的长度变化不会超过log(len)次
HDU 3746
求最少添加多少任意字符使得字符串由一个以上的循环节构成
先求出最小循环节,然后补全即可
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 1000010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
//Next[0]=0,Next[1]=0;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
FOR(i,,t){
scanf("%s",b+); m=strlen(b+);
doit();
int len=m-Next[m];
if(len==m) cout<<m<<endl;//无循环节
else if(m%len!=) cout<<len-m%len<<endl;//可扩展
else cout<<<<endl;//有循环节
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
HDU 1358
给出一个字符串s,问在[0, i]区间是否有完整的循环节,若有,输出i并输出循环次数
枚举这个i,next 2~len 运用定理
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 1000010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t,len;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
while(cin>>m&&m!=){
t++;
scanf("%s",b+);
doit();
cout<<"Test case #"<<t<<endl;
FOR(i,,m){
len=i-Next[i];
if(len!=i&&i%len==) cout<<i<<' '<<i/len<<endl;
}
cout<<endl;
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
POJ 2406
求循环节最大周期周期数,除一下就好了
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 1000010
char a[maxn],b[maxm];
int Next[maxm];
int n,m,t,len;
inline LL read(){
LL f=,ans=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(''<=ch&&ch<=''){ans=ans*+ch-'';ch=getchar();}
return ans*f;
}
void doit(){
int pre=;
Next[]=,Next[]=;
FOR(suf,,m){
while(pre>&&b[pre+]!=b[suf]) pre=Next[pre];
if(b[pre+]==b[suf]) pre++;
Next[suf]=pre;
}
return;
}
void kmp(){
int pre=,ans=;
//Next[0]=0,Next[1]=0;
FOR(suf,,n){
while(pre>&&b[pre+]!=a[suf]) pre=Next[pre];
if(b[pre+]==a[suf]) pre++;
if(pre==m) {ans++; pre=Next[pre];}
}
cout<<ans<<endl;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
while(true){
scanf("%s",b+); if(b[]=='.') break;
m=strlen(b+);
doit();
len=m-Next[m];
if(m%len) cout<<<<endl; else cout<<m/len<<endl;
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
hdu 4847
单字符串匹配 娱乐签到题
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
char xxx[]="doge";
char x[];
int Next[];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,char* y){
int lenx=strlen(x);
int leny=strlen(y);
int pre=,suf=,ans=;
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int ans=;
while(gets(x)){
int len=strlen(x);
FOR(i,,len){
if('A'<=x[i]&&x[i]<='Z') x[i]+='a'-'A';
}
ans+=kmp(xxx,x);
}
printf("%d\n",ans);
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
*2.最小最大表示法
IOI 2003WC(安徽 周源)的一个拾遗,核心思想是序化对象比对
int getmin(char* x,int len){
int i=,j=,k=;
while(i<len&&j<len){
if(k==len) break;
int t=x[(i+k)%len]-x[(j+k)%len];
if(t==) k++;
else{
if(t>) i=i+k+;
else j=j+k+;
if(i==j) j++;
k=;
}
}
return min(i,j);
}
模板
模板写法及变式(待更新)
对字符串a和b
若a=b(在循环意义上),则他们的最小序表示一定相同
将字符串s看作s与它的副本s’。
若s=s'(在循环意义上),则他们的最小序表示一定相同
假设当前两字符串相等且非最小序状态,给定初始指针ij
ij不变情况下后移并匹配直到失配,由于默认两字符串相等,则次小序的一方必须滚动到新的位置(从未匹配到的地方)使得自己可能取到更小的序
ij任意一方滚动到头时匹配结束->不同
ij匹配长度等于序列长->相同
显然,字符串的最小序一定能求出
hdu 3374
求循环节环状字符串最大最小序起点及循环节长度
kmp周期+表示法
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 2000010
char xx[];
int ans;
int getmin(char* x,int len){
int i=,j=,k=;
while(i<len&&j<len){
if(k==len) break;
int t=x[(i+k)%len]-x[(j+k)%len];
if(t==) k++;
else{
if(t>) i=i+k+;
else j=j+k+;
if(i==j) j++;
k=;
}
}
return min(i,j);
}
int getmax(char* x,int len){
int i=,j=,k=;
while(i<len&&j<len){
if(k==len) break;
int t=x[(i+k)%len]-x[(j+k)%len];
if(t==) k++;
else{
if(t<) i=i+k+;
else j=j+k+;
if(i==j) j++;
k=;
}
}
return min(i,j);
}
int Next[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next[pre];
Next[++suf]=++pre;
}
}
int kmp(char* x,char* y){
int lenx=strlen(x);
int leny=strlen(y);
int pre=,suf=,ans=;
prekmp(x,lenx);
while(suf<leny){
while(pre!=-&&y[suf]!=x[pre]) pre=Next[pre];
pre++; suf++;
if(pre>=lenx){
pre=Next[pre];
ans++;
}
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
while(scanf("%s",xx)!=EOF){
int len=strlen(xx);
prekmp(xx,len);
//FOR(i,0,len+1) cout<<Next[i];
if(len%(len-Next[len])!=) ans=; else ans=len/(len-Next[len]);
printf("%d %d %d %d\n",getmin(xx,len)+,ans,getmax(xx,len)+,ans);
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
hdu 2609
求环状字符串真实个数
表示法标准化处理+set去重
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
int n,cnt,lenx;set<string> aa;
char x[];
int getmin(char* x,int len){
int i=,j=,k=;
while(i<len&&j<len){
if(k==len) break;
int t=x[(i+k)%len]-x[(j+k)%len];
if(t==) k++;
else{
if(t>) i=i+k+;
else j=j+k+;
if(i==j) j++;
k=;
}
}
return min(i,j);
}
void getstr(char *x,int len){
x[len]='\0';
aa.insert(x);
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
while(scanf("%d",&n)!=EOF){
cnt=;
aa.clear();
FOR(i,,n){
scanf("%s",x);
lenx=strlen(x);
memcpy(x+lenx,x,lenx);
getstr(x+getmin(x,lenx),lenx);
}
printf("%d\n",SZ(aa));
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
善用memcpy!!!用法是memcpy(y,x.begin(),x.end()) (y<-x)
3.EKMP
int Next[maxn],ex[maxn];
void pre_EKMP(char* x,int lenx)
{
Next[]=lenx;
int j=;
while(j+<lenx && x[j]==x[j+]) j++;
Next[]=j;
int k=;
for(int i=;i<lenx;i++)
{
int p=Next[k]+k-;
int L=Next[i-k];
if(i+L<p+) Next[i]=L;
else
{
j=max(,p-i+);
while(i+j<lenx && x[i+j]==x[j])j++;
Next[i]=j;
k=i;
}
}
}
void EKMP(char *x,char *y)
{
int lenx=strlen(x);
int leny=strlen(y);
pre_EKMP(x,lenx);
int j=;
while(j<leny && j<lenx && x[j]==y[j]) j++;
ex[]=j;
int k=;
for(int i=;i<leny;i++)
{
int p=ex[k]+k-;
int L=Next[i-k];
if(i+L<p+) ex[i]=L;
else
{
j=max(,p-i+);
while(i+j<leny && j<lenx && y[i+j]==x[j])j++;
ex[i]=j;
k=i;
}
}
}
模板
模板写法及变式(待更新)(重要!!!勿忘!!!)
next[i]保存的是模式串X[0-len]与X[i-len]的最大公共前缀长度,s[0-next[i]-1]为最大公共前缀
其中,next数组的0号位为值len(恒定),1号位为暴力求出,第二位起的其余位为正常位,直到第lenX-1位
ex[i]保存的是模式串X[0-len]与匹配串S[i-len]的最大公共前缀长度,s[0-ex[i]-1]为最大公共前缀
其中,ex数组的0号位为暴力求出,第一位起的其余位为正常位,直到第lenS-1位
主要的指针为现有的最大已匹配前缀的首位K和现在假设的匹配前缀的首位I
最大已匹配前缀 S[K~K+next[K]-1]
若我们保证恒有I>K
则假设的匹配前缀的一部分S[(I~I+next[K-I]-1)=(0~K-I)=(K~I)]
若这部分包含于最大已匹配前缀,则必定失配,若不失配,则最大已匹配前缀名不副实
这是K+next[K]-1>I+next[K-I]-1时的情况
否则就更新指针逐位匹配 来更新K
求解next时就是S-S‘
求解ex时就是S-X
几乎没什么区别
所以说kmp和exkmp有个鬼的关系啊。
kmp是一个以失配为核心的算法,exkmp是个以匹配为核心的东西。。。这玩意更接近表示法一点吧。。。。
hdu 3613
提供密码表和一段密文+明文的信息
明文可能不完整,密文一定完整,求最小的完整密文+明文
不管三七二十一搞个全转换成明文的串出来,以信息为匹配串,明文为模式串做exkmp
则最小长度的密文为最小满足i+ex[i]-1=len-1的i对应的S[0~i-1]
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 110000
char x[maxn],y[maxn],z[maxn],a[];
int Next[maxn],ex[maxn];
int t;
void pre_EKMP(char* x,int lenx)
{
Next[]=lenx;
int j=;
while(j+<lenx && x[j]==x[j+]) j++;
Next[]=j;
int k=;
for(int i=;i<lenx;i++)
{
int p=Next[k]+k-;
int L=Next[i-k];
if(i+L<p+) Next[i]=L;
else
{
j=max(,p-i+);
while(i+j<lenx && x[i+j]==x[j])j++;
Next[i]=j;
k=i;
}
}
}
//
void EKMP(char *x,int lenx,char *y,int leny)
{
//int lenx=strlen(x);
//int leny=strlen(y);
pre_EKMP(x,lenx);
int j=;
while(j<leny && j<lenx && x[j]==y[j]) j++;
ex[]=j;
int k=;
for(int i=;i<leny;i++)
{
int p=ex[k]+k-;
int L=Next[i-k];
if(i+L<p+) ex[i]=L;
else
{
j=max(,p-i+);
while(i+j<leny && j<lenx && y[i+j]==x[j])j++;
ex[i]=j;
k=i;
}
}
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
while(t--){
map<char,char> b;
scanf("%s%s",x,y);
FOR(i,,strlen(x)){
a[i+'a']=x[i];b[x[i]]=i+'a';}
int lenl=strlen(y);
FOR(i,,lenl){
z[i]=b[y[i]];}
//cout<<endl;
//FOR(i,0,lenl) cout<<z[i];
//cout<<"**"<<endl;
EKMP(z,lenl,y,lenl);
//cout<<"**";
//FOR(i,0,lenl)
//cout<<ex[i];
int ii;
for(ii=;ii<lenl;ii++) if(ii+ex[ii]>=lenl&&ex[ii]<=ii) break;
int lll=lenl-ex[ii];
FOR(j,,lll)
printf("%c",y[j]);
FOR(j,,lll)
printf("%c",b[y[j]]);
printf("\n");
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
hdu 4763
找出最大的公共前后缀 ,使得原串在去掉前后缀后依然能够与此公共前后缀匹配成功
用kmp的next枚举公共前后缀,用exkmp的next检验是否依然匹配成功
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
char x[maxn];
int n;
int Next[maxn],ex[maxn];
void pre_EKMP(char* x,int lenx)
{
Next[]=lenx;
int j=;
while(j+<lenx && x[j]==x[j+]) j++;
Next[]=j;
int k=;
for(int i=;i<lenx;i++)
{
int p=Next[k]+k-;
int L=Next[i-k];
if(i+L<p+) Next[i]=L;
else
{
j=max(,p-i+);
while(i+j<lenx && x[i+j]==x[j])j++;
Next[i]=j;
k=i;
}
}
}
int Next1[maxn];
void prekmp(char* x,int len){
int pre=-,suf=;
Next1[]=-;
while(suf<len){
while(pre!=-&&x[suf]!=x[pre]) pre=Next1[pre];
Next1[++suf]=++pre;
}
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&n);
FOR(i,,n){
scanf("%s",x);
int lenx=strlen(x);
pre_EKMP(x,lenx);
prekmp(x,lenx);
int j,ans=;
bool flag=false;
for(j=Next1[lenx];Next1[j]!=-;j=Next1[j]){
FOR(k,j,lenx-j)
if(Next[k]>j-) {ans=j;flag=true;break;}
if(flag) break;
}
printf("%d\n",ans);
} //system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
4.manache
#define maxma 2100000
char ma[maxma];
int mp[maxma],t;
void manache(char *x,int len){
int l=;
len=strlen(x);
ma[l++]='-';
ma[l++]='+';
FOR(i,,len)
ma[l++]=x[i],ma[l++]='+';
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
return;
}
模板
模板写法及变式(待更新)
使abcde等价于#$a$b$c$d$e$*[0,len*2+1]
使得所有回文串的两侧都为$,而$又始终为奇数
mp[i]为以i为中心的字符串的回文长度,对应[i-mp[i]+1,i+mp[i]-1]
由于所有回文串的两侧都为$,而$又始终为奇数,则对应原串[(i-mp[i]+1+1)/2-1,(i+mp[i]-1-1)/2-1]
即[(i-mp[i])/2,(i+mp[i])/2-2]
相似的,主要的指针为现有的最大已匹配回文串中心ID和现在假设的匹配回文串中心的首位I
恒保证ID<=I 如果[id-mp[id]+1,id+mp[id]-1]包括i的话,即i<=id+mp[id]-1,则其的最大回文长度为min(mp[2*id-i],mx-i) //2id-i-id-i=mx-i-max
否则不存在已经求得的部分,默认从1开始
之后继续更新指针逐位匹配 来更新ID
好像exkmp啊。。。。。。
hdu 3613
一个宝石序列,其中的每种宝石都有其价值
将该序列分成两部分,总价值为部分的宝石价值之和当且仅当该部分为回文串
枚举第一部分中心I(1,I,2*I-1),再去检验第二部分是否满足回文性质(2*l,l+len,2*len)
manache0号位必失配,1号位为空
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxma 1100000
#define maxn 500010
int val[];
int f[maxn];
int n;
char x[maxn];
char ma[maxma];
int mp[maxma],t;
int idx(char x){
return x-'a';
}
void manache(char *x,int len){
int l=;
len=strlen(x);
ma[l++]='-';
ma[l++]='$';
FOR(i,,len)
ma[l++]=x[i],ma[l++]='$';
ma[l]='#';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&n);
FOR(pp,,n){
FOR(i,,)
scanf("%d",&val[i]);
scanf("%s",x);
int len=strlen(x);
f[]=val[idx(x[])];
FOR(i,,len)
f[i]=f[i-]+val[idx(x[i])];
manache(x,strlen(x));
int ans=;
FOR(k,,len-){
int tmp=;
int cnt=mp[k+]-;
if(cnt==k+) tmp+=f[k];
cnt=mp[k+len+]-;
if(cnt==len-k-)
tmp+=f[len-]-f[k];
ans=max(tmp,ans);
}
printf("%d\n",ans);
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
poj 3974
求最大回文串
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 2100000
char ch[maxn],ma[maxm];
int mp[maxm],t;
void manache(char x[],int len){
int l=;
//
ma[l++]='$';
ma[l++]='#';
FOR(i,,len-)
ma[l++]=x[i],ma[l++]='#';
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l-){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
int ans=;
FOR(i,,l-) ans=max(ans,mp[i]);
printf("Case %d: %d\n",++t,ans-);
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
while(scanf("%s",ch)!=EOF){
if(ch[]=='E'&&ch[]=='N'&&ch[]=='D') break;
manache(ch,strlen(ch));
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
hdu 4513
求最大浮动回文串
更新mp时加上单调减少的限制即可
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 100010
#define maxm 210000
int aa[maxn],ma[maxm];
int a[maxn],mp[maxm],t;
void manache(int x[],int len){
int l=;
//
ma[l++]=-;
ma[l++]=-;
FOR(i,,len-)
ma[l++]=x[i],ma[l++]=-;
ma[l]=-;//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l-){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]&&ma[i-mp[i]]<=ma[i-mp[i]+]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
//FOR(i,0,l-1) cout<<mp[i];
//cout<<endl;
int ans=;
FOR(i,,l-) ans=max(ans,mp[i]);
printf("%d\n",ans-);
//printf("Case %d: %d\n",++t,ans-1);
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
int T,n;
scanf("%d",&T);
while(T--){
//if(ch[0]=='E'&&ch[1]=='N'&&ch[2]=='D') break;
scanf("%d",&n);
FOR(i,,n-)
scanf("%d",&a[i]);
manache(a,n);
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
hdu 3294
凯撒移位+求第一个长度至少为二的最大回文
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_macro
#define INF (1<<29)
#define MOD 1000000007ll
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define FORD(i,j,k) for(int i=j;i>=k;i--)
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxn 1000010
#define maxm 2100000
char ch[maxn],ma[maxm];
int mp[maxm],t,xx;
void manache(char x[],int len){
int l=;
//
ma[l++]='$';
ma[l++]='#';
FOR(i,,len-)
ma[l++]=x[i],ma[l++]='#';
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l-){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
int ans=;
FOR(i,,l-) if(mp[ans]<mp[i]) ans=i;
if(mp[ans]<) printf("No solution!\n");
else{
printf("%d %d\n",(ans-mp[ans])/,(ans-mp[ans])/+mp[ans]-);
FOR(i,ans-mp[ans]+,ans+mp[ans]-)
if(ma[i]!='#') printf("%c",(ma[i]-'a'-xx+)%+'a');
printf("\n");
}
//printf("Case %d: %d\n",++t,ans-1);
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
t=;
char chc;
while(scanf(" %c%s",&chc,ch)!=EOF){
xx=chc-'a';
//if(ch[0]=='E'&&ch[1]=='N'&&ch[2]=='D') break;
manache(ch,strlen(ch));
}
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
//system(pause);
return ;
}
ac代码
hdu 3068
求最长回文 模板题
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
char xxx[]="doge";
char x[];
#define maxma 2100000
char ma[maxma];
int mp[maxma],t;
int manache(char *x,int len){
int l=;
len=strlen(x);
ma[l++]='-';
ma[l++]='+';
FOR(i,,len)
ma[l++]=x[i],ma[l++]='+';
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
}
int maxx=;
FOR(i,,l){
maxx=max(maxx,mp[i]-);
}
return maxx;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
while(scanf("%s",x)!=EOF){
int len=strlen(x);
printf("%d\n",manache(x,len)); }
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
5.Trie
#define maxnode 100010
#define maxsize 30
struct Trie{
int ch[maxnode][maxsize];
int val[maxnode];
int sz;
Trie(){sz=;memset(ch[],,sizeof(ch[]));memset(val,,sizeof(val));return;}
int idx(char c) {return c-'a';}
void insert(char *x,int valx){
int u=,len=strlen(x);
FOR(i,,len){
int c=idx(x[i]);
if(!ch[u][c]){
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=valx;
}
int insert(char *x){
int u=,len=strlen(x);
FOR(i,,len){
int c=idx(x[i]);
if(!ch[u][c]) return ;
u=ch[u][c];
}
return val[u];
}
};
模板
貌似没啥可说的。。。主要难点是在上面挂各种东西
poj 3376
给n个串,求串+串(n*n个)为回文串的个数
n个串插进trie,顺手插进manache跑出来的结果(除去当前位之外的字符串是否为回文串),结尾标记照样加上
将反串放到trie里查询,如果反串为长串,就加上此节点下挂的串剩余下来的串为回文串的个数(manache跑出来的)减掉在此节点结束的字符串数
如果反串为短串(包括长度相等),就在查询当前位之外为回文串的基础上计入在当前查询节点结束的字符串数
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxnode 2000010
#define maxsize 26
#define maxma 4000010
#define maxn 2000010
char ma[maxma];
int mp[maxma],t,lenx,n;
int w[maxn],bg[],ed[]; char x[maxn];char xx[]; struct Trie{
int ch[maxnode][maxsize];
int val[maxnode],e[maxnode];
int sz;
int idx(char c) {return c-'a';}
void iinsert(char *x,int len,int *cc){
int u=;
FOR(i,,len){
int c=idx(x[i]);
if(!ch[u][c]){
//kk[u][c]=x[i];
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
val[u]+=cc[i];
}
e[u]++;
return;
}
LL xquery(char *x,int len){
int l=; //
ma[l++]='-';
ma[l++]='+';
FOR(i,,len)
ma[l++]=x[i],ma[l++]='+',w[i]=;
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
if(i+mp[i]>=l-)
w[(i-mp[i])/] = ; }
LL anss=;
int c=,i=,u=;//cout<<endl;
bool flag=false;
for(i=;i<len;i++){
c=idx(x[i]);
if(!ch[u][c]) {flag=true;break;}
u=ch[u][c];
if(e[u]&&w[i+]) anss+=e[u]; }
if(!flag) anss+=val[u]-e[u];
return anss;
}
} tt;
void manache(char *x,int len){
int l=;
//len=strlen(x);
ma[l++]='-';
ma[l++]='+';
FOR(i,,len)
ma[l++]=x[i],ma[l++]='+',w[i]=;
ma[l]='*';//0,l not_fix
int mx=,id=;///mp[i] (length+1)/2
FOR(i,,l){
mp[i]=mx>i?min(mp[*id-i],mx-i):;// 2id-i-id-i,mx-i-max
while(ma[i+mp[i]]==ma[i-mp[i]]) mp[i]++;
if(i+mp[i]>mx) {
mx=i+mp[i];
id=i;
}
if(i+mp[i]>=l-){
w[(i-mp[i])/] = ;} }
tt.iinsert(x,len,w+);
return;
} int main(){
int suml=;tt.sz=;
scanf("%d",&n);
FOR(i,,n){
scanf("%d",&lenx);
scanf("%s",x+suml);
manache(x+suml,lenx);
bg[i]=suml;suml+=lenx;ed[i]=suml; }
LL ans=;
FOR(i,,n){
int ccc=ed[i]-bg[i];
FORD(l,ccc-,-) xx[ccc-l-]=x[bg[i]+l];
ans+=tt.xquery(xx,ccc);
}
printf("%lld\n",ans);
return ;
}
ac代码
UVA11362
给n个字符串,看是否有一个串a为串b的前缀。
模板题
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxnode 100010
#define maxsize 27
int t,n,flag;
char s[maxnode];
struct Trie{
int ch[maxnode][maxsize];
int val[maxnode];
int sz;
void init(){sz=;memset(ch[],,sizeof(ch[]));memset(val,,sizeof(val));return;}
int idx(char c) {return c-'';}
void insert(char *x,int valx){
int u=,len=strlen(x);
FOR(i,,len){
int c=idx(x[i]);
//cout<<sz;
if(ch[u][c]==){
memset(ch[sz],,sizeof(ch[sz]));
if(i!=len-)val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
if(val[u]==) flag=false;
}
if(val[u]==) flag=false;
val[u]=;
return;
}
int query(char *x){
int u=,len=strlen(x);
FOR(i,,len){
int c=idx(x[i]);
if(!ch[u][c]) return ;
u=ch[u][c];
}
return val[u];
}
};
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
while(t--){
Trie tt;
flag=true;
tt.init();
flag=true;
scanf("%d",&n);
FOR(i,,n){
scanf("%s",s);
if(flag)
tt.insert(s,); }
if(flag) printf("YES\n"); else printf("NO\n");
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
bzoj 1212
给出 N个单词M个句子,问每个句子中包含这些单词的最长前缀是多少。
不停地把模式串放到trie中查询,得到的结果放进dp里
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxnode 10010
#define maxsize 30
bool f[];
int n,m;
char x[];
struct Trie{
int ch[maxnode][maxsize];
int val[maxnode];
int sz;
void init(){sz=;memset(ch[],,sizeof(ch[]));memset(val,,sizeof(val));return;}
int idx(char c) {return c-'a';}
void insert(char *x){
int u=,len=strlen(x);
FOR(i,,len){
int c=idx(x[i]);
if(!ch[u][c]){
memset(ch[sz],,sizeof(ch[sz]));
//val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=;
}
void query(char *x,int jj,int len){
int u=;
FOR(i,jj,len){
int c=idx(x[i]);
if(val[u]==) f[i]=;
if(!ch[u][c]) return ;
u=ch[u][c];
//cout<<u;
}
if(val[u]==) f[len]=;
return;
//return val[u];
}
};
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
Trie tt;tt.init();
scanf("%d%d",&n,&m);
FOR(i,,n){
scanf("%s",x);tt.insert(x);}
FOR(j,,m){
scanf("%s",x);
f[]=;int len=strlen(x);
FOR(i,,len+) f[i]=;
FOR(i,,len+)
if(f[i-]) tt.query(x,i-,len);
FORD(i,len,-)
if(f[i]) {printf("%d\n",i);;break;}
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
bzoj 1590
给出n+m个01串,问对于这m个串中的所有串,各自跟n个串中的多少串有相同前缀(前缀长度必须等于两者长度的较小者)
每个节点存下下挂节点数和在这里结束的节点数就好了
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxnode 500010
#define maxsize 2
int e[maxnode];
int ch[maxnode][maxsize];
int val[maxnode];
int sz,len,c,n,m,lens;
int x[maxnode];
void init(){sz=;memset(ch[],,sizeof(ch[]));memset(val,,sizeof(val));return;} //int idx(char c) {return c-'a';} int query(int *x,int len){
int u=,ans=;
//cout<<len<<endl;
//len=strlen(x);
FOR(i,,len){
int c=x[i];
if(!ch[u][c]) return ans;
u=ch[u][c];ans+=e[u];
}
return ans+val[u];
}
void insert(){
scanf("%d",&len);
int u=;
FOR(i,,len){
scanf("%d",&c);
if(!ch[u][c]){
memset(ch[sz],,sizeof(ch[sz]));
ch[u][c]=sz++;
}
val[u]++;
u=ch[u][c];
}
e[u]++;
return;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d%d",&n,&m);
init();
FOR(i,,n) insert(); FOR(i,,m){
scanf("%d",&lens);
FOR(i,,lens) scanf("%d",&x[i]);
//cout<<"##"<<lens<<endl;
printf("%d\n",query(x,lens));
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
loj 10050
在给定的n个整数 中选出两个进行异或运算,得到的结果最大是多少?
数字统一看成从高到低30位的二进制串,插入01tri,然后贪心
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
#define maxnode 5000010
#define maxsize 2
int t,ans;
int a[];
struct Trie10{
int ch[maxnode][maxsize];
int val[maxnode];
int sz;
void init(){
sz=;memset(ch[],,sizeof(ch[]));memset(val,,sizeof(val));
}
void insert(int x){
int u=;
FORD(i,,-){
int c=(x>>i)&;
if(!ch[u][c]){
memset(ch[sz],,sizeof(ch[sz]));
ch[u][c]=sz++;
}
u=ch[u][c];
}
return;
}
int query(int x){
int u=,ans=;
FORD(i,,-){
int c=(x>>i)&;
if(ch[u][!c]){
u=ch[u][!c]; ans+=<<i;
}
else u=ch[u][c];
}
return ans;
}
};
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
scanf("%d",&t);
Trie10 tt;
tt.init();
ans=;
FOR(i,,t){
scanf("%d",&a[i]);
tt.insert(a[i]);
}
FOR(i,,t)
ans=max(tt.query(a[i]),ans);
printf("%d",ans);
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
hdu 3746
提供单词及其词性和句子,保证句子中的单词都是已经给定的,判断语法对不对
你是谁???为啥会出现在这个题单里???
STL+语法分层,跟字符串匹配没关系,直接cin
//#define LOCAL
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
// X_INIT=0 mem_Macro
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define FOR(i,j,k) for(int i=j;i<k;i+=1)
#define FORD(i,j,k) for(int i=j;i>k;i-=1)
#define uLL unsigned long long
#define LL long long
#define SZ(x) int(x.size())
#define pb push_back
int n,m,len;
string x;
map<string,int> fun; //把每种词标号
map<string,int> num; //将题目中给出的词标号
map<string,char> str; //记录每种主语宾语谓语介词短语的每种形式,打表
map<string,int> ste; //每种句子形式,打表
void init()
{
fun["n."]=;
fun["pron."]=;
fun["adj."]=;
fun["adv."]=;
fun["prep."]=;
fun["art."]=;
fun["vt."]=;
fun["vi."]=;
fun["v."]=; str[""]='A'; //介词短语
str[""]='A';
str[""]='A';
str[""]='S'; //主/宾语
str[""]='S';
str[""]='S';
str[""]='I'; //不及物谓语
str[""]='I';
str[""]='T'; //及物谓语
str[""]='T';
str[""]='V'; //通用谓语
str[""]='V';
//句子可能的总体结构
ste["SI"]=;
ste["STS"]=;
ste["SV"]=;
ste["SVS"]=;
ste["ASI"]=;
ste["ASTS"]=;
ste["ASV"]=;
ste["ASVS"]=;
ste["SAI"]=;
ste["SATS"]=;
ste["SAV"]=;
ste["SAVS"]=;
ste["SIA"]=;
ste["STAS"]=;
ste["SVA"]=;
ste["SVAS"]=;
ste["STSA"]=;
ste["SVSA"]=;
return;
};
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
string x,y;
init();
cin>>n>>m;
//scanf("%d%d",&n,&m);
FOR(i,,n+){
//scanf("%s%s",&x,&y);
cin>>x>>y;
num[x]=fun[y];
}
FOR(pp,,m){
string m="";
while(cin>>x){ len=x.length();
if(x[]<'a') x[]+='a'-'A';
if(x[len-]=='.'){x.erase(len-,);m+=''+num[x];break;}
if(x[len-]==',') x.erase(len-,); m+=''+num[x];
}
string idx="",id="";
FOR(i,,m.length()){
id+=m[i];
if(str[id]) idx+=str[id],id="";
}
if(id!="") printf("NO\n");
else{
if(ste[idx]) printf("YES\n");else printf("NO\n");
}
}
//system("pause");
#ifdef LOCAL
fclose(stdin);
fclose(stdout);
#endif
return ;
}
ac代码
(25+4/25+4)复健-KMP/EKMP/manache/Trie的更多相关文章
- 2019NOIP算法复健+学习
前言: 原本因为kma太弱,很多算法没学学了也不会用,打算设置密码给自己看.后来想了想,觉得也没有必要,既然决定了要学些东西到脑子里,就没什么好丢人的. 注:"×"意为完全没学,& ...
- PAT 甲级 1006 Sign In and Sign Out (25)(25 分)
1006 Sign In and Sign Out (25)(25 分) At the beginning of every day, the first person who signs in th ...
- 【PAT】1020 Tree Traversals (25)(25 分)
1020 Tree Traversals (25)(25 分) Suppose that all the keys in a binary tree are distinct positive int ...
- 【PAT】1052 Linked List Sorting (25)(25 分)
1052 Linked List Sorting (25)(25 分) A linked list consists of a series of structures, which are not ...
- 【PAT】1060 Are They Equal (25)(25 分)
1060 Are They Equal (25)(25 分) If a machine can save only 3 significant digits, the float numbers 12 ...
- 【PAT】1032 Sharing (25)(25 分)
1032 Sharing (25)(25 分) To store English words, one method is to use linked lists and store a word l ...
- 【PAT】1015 德才论 (25)(25 分)
1015 德才论 (25)(25 分) 宋代史学家司马光在<资治通鉴>中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得 ...
- 1003 Emergency (25)(25 point(s))
problem 1003 Emergency (25)(25 point(s)) As an emergency rescue team leader of a city, you are given ...
- 1002 A+B for Polynomials (25)(25 point(s))
problem 1002 A+B for Polynomials (25)(25 point(s)) This time, you are supposed to find A+B where A a ...
随机推荐
- SVG 新手入门
svg 入门新认知 一.第一步创建设置svg <svg width="100%" height="500"> </svg> 设置粗细 5 ...
- 使用Blazor Server 线路处理程序 (circuit handler)跟踪打开的SignalR连接
Blazor服务器允许定义线路处理程序(circuit handler)代码,该处理程序(handler)允许在更改用户线路状态时运行此代码. 线路处理程序(circuit handler)是通过从C ...
- JS模块规范:AMD,CMD,CommonJS
浅析JS模块规范 随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比 ...
- 使用AtomicStampedReference<T>的大坑
//在初始化的时候会把引用和时间戳存到pair中 AtomicStampedReference<Integer> integerAtomicStampedReference = new A ...
- 本地Hadoop集群搭建
什么是Hadoop? Hadoop是一个开源的Apache项目,通常用来进行大数据处理. Hadoop集群的架构: master节点维护分布式文件系统的所有信息,并负责调度资源分配,在Hadoop集群 ...
- Java集合02——三分钟了解你必须掌握的两个Set
上一篇文章我们说到了 List ,本章开始,我们将继续讲解Set相关的知识.关注公众号「Java面典」了解更多 Java 知识点. Set 是一个无重复对象的集合类.值的重复与否是根据对象的 hash ...
- Win10下如何安装和搭建appium自动化测试环境
转:https://www.cnblogs.com/huainanhai/p/11577419.html 安装Android SDK https://www.jianshu.com/p/2acdc1d ...
- 关于SDL的一些坑:找不到WinMain,不显示控制台,添加链接库等
目录: 用CMake构建SDL时报错 Gcc添加链接库 Gcc找不到入口(WinMain) 让SDL启动时不带控制台窗口 用CMake构建SDL时报错 root@ubuntu:~/SDL# cmake ...
- swagger2 Illegal DefaultValue null for parameter type integer
问题,为了方便调试,引入了swagger2,但是在第一次访问的时候总是报 Illegal DefaultValue null for parameter type integer 让人看着很不输入 定 ...
- javaScript 基础知识汇总 (十二)
1.属性的标志和描述符 属性的标志 对象属性除value外还有三个特殊属性,即标志 writable ----如果为true,则可以修改,否则它只是只读的. enumerable ----如果为tru ...