扩展KMP题目
hdu4333
/* 题意:字符串s[0..n-1],每次把最后一个字符放到前面,求形成的字符串比最初串分别小,相同,大于的个数 因为是为了练习扩展KMP所以肯定是扩展KMP, 为了循环方便,在后面复制字符串,求出next[]数组后, 如果next[i]>n那么肯定相等,如果小于就判断s[ next[i] ]和 s[ i+next[i] ]的大小判断 trick:题目求得是形成的不同的字符串的个数,可以知道相等的字符串肯定只有一个, 而从0..n-1,第二个next[i]大于n那么这个i就是该字符串的循环节; */ #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int N=100000+10; char s[N*2]; int next[N*2],n; void getNext(char *s,int next[]){ int nn=strlen(s); next[0]=nn; int p=0; while (s[p+1] && s[p]==s[p+1]) p++; next[1]=p; int k=1; for (int i=2;i<nn;i++){ int p=k+next[k]-1, L=next[i-k]; if (i+L<=p) next[i]=L; else{ int j=p-i+1; if (j<0) j=0; while (i+j<nn && s[i+j]==s[j]) j++; next[i]=j; k=i; } } } void work(){ int ret1,ret2,ret3; ret1=ret2=ret3=0; getNext(s,next); for (int i=0;i<n;i++){ if (i!=0 && next[i]>=n) break; if (next[i]<n) { if (s[ i+next[i] ]<s[ next[i] ]) ret1++; else ret3++; }else ret2++; } printf("%d %d %d\n",ret1,ret2,ret3); } int main(){ int T,cas=0;scanf("%d",&T); while (T--){ scanf("%s",s); printf("Case %d: ",++cas); n=strlen(s); for (int i=0;i<n;i++){ s[n+i]=s[i]; }s[n+n]='\0'; // cout<<s<<endl; work(); } return 0; }
hdu3613
1 /* 2 题意:将一个串分成俩个串,如果是回文串值就是所有字符的值,如果不是值就为0 3 问你最大的值是多少; 4 5 分析:因为是扩展KMP的题,很容易想到用扩展KMP判读是否是回文串,而且题目的 6 特点是至少有一端是端点,这很容易想到前缀和后缀,然后思路就出来了; 7 首先将串s逆转变成s1,求出s的所有后缀与s1的最长公共子串的长度, 8 这样分割成两段的后面一段,判断该段是否是回文只要判断最长长度是否等于后面一段的 长度就可以了了 9 前面一段类似,只是要求出s1的所有后缀与s的最长公共子串的长度,判断方法类似 10 11 12 */ 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #include<cmath> 19 #include<vector> 20 using namespace std; 21 const int N=500000+10; 22 char s[N],s1[N]; 23 int v[30]; 24 int ext1[N],ext2[N],next[N]; 25 void getNext(char *s,int next[]){ 26 int nn=strlen(s); 27 next[0]=nn; 28 int p=0; 29 while (s[p+1] && s[p]==s[p+1]) p++; 30 next[1]=p; 31 int k=1, L; 32 for (int i=2;i<nn;i++){ 33 p=k+next[k]-1; L=next[i-k]; 34 if (i+L<=p) next[i]=L; 35 else { 36 int j=p-i+1; 37 if (j<0) j=0; 38 while (i+j<nn && s[i+j]==s[j]) j++; 39 next[i]=j; k=i; 40 } 41 } 42 43 } 44 void getExtend(char *s,char *T,int *ext){ 45 getNext(s,next); 46 int p=0, nn=strlen(s); 47 while (s[p] && s[p]==T[p]) p++; 48 ext[0]=p; 49 int k=0, L; 50 for (int i=1;i<nn;i++){ 51 p=k+ext[k]-1; L=next[i-k]; 52 if (i+L<=p) ext[i]=L; 53 else { 54 int j=p-i+1; 55 if(j<0) j=0; 56 while (i+j<nn && s[i+j]==T[j]) j++; 57 ext[i]=j; k=i; 58 } 59 } 60 } 61 int val[N]; 62 void work(){ 63 memset(val,0,sizeof(val)); 64 int len=strlen(s); 65 for (int i=0;i<len;i++) val[i+1]=val[i]+v[s[i]-'a']; 66 67 68 69 for (int i=len-1;i>=0;i--) s1[len-i-1]=s[i]; 70 s1[len]='\0'; 71 // cout<<s<<endl<<s1<<endl; 72 getExtend(s1,s,ext1); 73 getExtend(s,s1,ext2); 74 75 int ret=0; 76 for (int i=1;i<len;i++){ 77 int l1=i,l2=len-l1; 78 int tmp=0; 79 if (ext1[len-i]==l1) tmp+=val[i]; 80 if (ext2[i]==l2) tmp+=val[len]-val[i]; 81 if (tmp>ret) ret=tmp; 82 } 83 printf("%d\n",ret); 84 } 85 int main(){ 86 int T;scanf("%d",&T); 87 while (T--){ 88 for (int i=0;i<26;i++) scanf("%d",v+i); 89 scanf("%s",s); 90 work(); 91 } 92 return 0; 93 } 94 /* 95 4 96 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 97 aaadbbbd 98 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 99 ab 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 101 aba 102 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 103 aaaaaaaaaaaaaaa 104 105 */
poj1699
1 /* 2 题意:给你n个串,求最短的串使得n个串都包含在里面(n<=10) 3 从n的数据范围就可以看出状态压缩dp 4 dp[i][j]表示已经包含了"i"个串,且最后一个串是j的最小长度 5 预处理出s[i]的后缀与s[j]的前缀的最长公共子串 6 7 */ 8 #include<cstdio> 9 #include<cstring> 10 #include<iostream> 11 #include<cmath> 12 #include<vector> 13 #include<algorithm> 14 using namespace std; 15 const int N=20+10; 16 char s[N][N]; 17 int n,next[N],mz[N][N],ext[N]; 18 void getNext(char *s,int *next){ 19 int nn=strlen(s); 20 next[0]=nn; 21 int p=0; 22 while (s[p+1] && s[p]==s[p+1]) p++; 23 next[1]=p; 24 int k=1, L; 25 for (int i=2;i<nn;i++){ 26 p=k+next[k]-1; L=next[i-k]; 27 if (i+L<=p) next[i]=L; 28 else{ 29 int j=p-i+1; 30 if (j<0) j=0; 31 while (i+j<nn && s[i+j]==s[j]) j++; 32 next[i]=j; k=i; 33 } 34 } 35 } 36 void getExtend(char *s,char *T,int ext[]){ 37 getNext(s,next); 38 int nn=strlen(s); 39 int p=0; 40 while (s[p] && T[p] && s[p]==T[p]) p++; 41 ext[0]=p; 42 int k=0,L; 43 for (int i=1;i<nn;i++){ 44 p=k+ext[k]-1; L=next[i-k]; 45 if (i+L<=p) ext[i]=L; 46 else { 47 int j=p-i+1; 48 if (j<0) j=0; 49 while (i+j<nn && s[i+j]==T[j]) j++; 50 ext[i]=j; k=i; 51 } 52 } 53 } 54 void init(){ 55 memset(mz,0,sizeof(mz)); 56 for (int i=0;i<n;i++){ 57 for (int j=0;j<n;j++){ 58 if (i==j) continue; 59 getExtend(s[i],s[j],ext); 60 int nn=strlen(s[i]); 61 for (int k=0;k<nn;k++){ 62 if (ext[k]==nn-k) { 63 mz[i][j]=nn-k; break; 64 } 65 } 66 } 67 } 68 /*for (int i=0;i<n;i++){ 69 for (int j=0;j<n;j++){ 70 cout<<mz[i][j]<<" "; 71 }cout<<endl; 72 }*/ 73 } 74 const int NN=1<<10; 75 int dp[NN][10]; 76 void Min(int &x,int y){ 77 if (x==-1) x=y; 78 else x=min(x,y); 79 } 80 void work(){ 81 memset(dp,-1,sizeof(dp)); 82 for (int i=0;i<n;i++){ 83 dp[1<<i][i]=strlen(s[i]); 84 } 85 for (int i=0;i<(1<<n);i++){ 86 for (int j=0;j<n;j++){ 87 if (dp[i][j]==-1) continue; 88 for (int k=0;k<n;k++){ 89 if ( i&(1<<k) ) continue; 90 Min(dp[i^(1<<k)][k],dp[i][j]+strlen(s[k])-mz[j][k]); 91 } 92 } 93 } 94 int ret=-1; 95 for (int i=0;i<n;i++){ 96 Min(ret,dp[(1<<n)-1][i]); 97 } 98 cout<<ret<<endl; 99 100 } 101 int main(){ 102 int T;scanf("%d",&T); 103 while (T--){ 104 scanf("%d",&n); 105 for (int i=0;i<n;i++) scanf("%s",s[i]); 106 init(); 107 work(); 108 } 109 return 0; 110 }