题目:POJ3080 http://poj.org/problem?id=3080
题意:对于输入的文本串,输出最长的公共子串,如果长度相同,输出字典序最小的。
这题数据量很小,用暴力也是16ms,用后缀数组可以到0ms,但我不会XD。
暴力:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 char str[15][65],ans[65]; 5 int main(){ 6 int T,n; scanf("%d", &T); 7 while (T--){ 8 memset(ans,0,sizeof(ans)); 9 scanf("%d", &n); 10 for (int i = 0; i < n; i++) scanf("%s", str[i]); 11 12 for (int i = 0; i < strlen(str[0]); i++) 13 for (int j = i + 2; j < strlen(str[0]); j++){ 14 char s[65];//子串 15 strncpy(s, str[0] + i, j - i + 1);///strncpy 16 s[j - i + 1] = '\0'; 17 18 int flag = 1; 19 for (int k = 1; flag && k < n; k++) 20 if (strstr(str[k], s) == NULL) 21 flag = 0; 22 ///匹配成功,判长度和字典序 23 if (flag && (j - i + 1 > strlen(ans) || (j - i + 1 == strlen(ans)&&strcmp(ans, s)>0) ) ) 24 strcpy(ans, s); 25 } 26 27 if (strlen(ans) < 3) puts("no significant commonalities"); 28 else puts(ans); 29 } 30 return 0; 31 }
KMP:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 char str[15][65],ans[65]; 6 int next[65]; 7 //计算串str的next数组 8 void getnext(char *str){ 9 int len=strlen(str); 10 next[0]=next[1]=0; 11 for(int i=1;i<len;i++){ 12 int j=next[i]; 13 while(j&&str[i]!=str[j]) j=next[j];//一直回溯j直到str[i]==str[j]或j减小到0 14 next[i+1]=str[i]==str[j]?j+1:0;//更新next[i+1] 15 } 16 } 17 //返回值是串S中第一次出现串T的开始位置 18 int KMP(char *S,char *T){ 19 int l1=strlen(S),l2=strlen(T); 20 int j=0; 21 for(int i=0;i<l1;i++){ 22 while(j&&S[i]!=T[j]) j=next[j]; 23 if(S[i]==T[j]) j++; 24 if(j==l2) return i-l2+1; 25 } 26 return -1;//若一直匹配不成功则返回-1 27 } 28 29 int main(){ 30 int T,n; 31 scanf("%d", &T); 32 while(T--){ 33 memset(ans,0,sizeof(ans)); 34 scanf("%d", &n); 35 for(int i=0;i<n;i++) scanf("%s", str[i]); 36 37 for(int i=0; i<strlen(str[0]); i++)//把第一个串的每一个子串当作模板串,求next数组,并和后面的每一个串去匹配 38 for(int j=i+2; j<strlen(str[0]); j++){ 39 char s[65]; 40 strncpy(s, str[0] + i, j - i + 1);///strncpy 41 s[j - i + 1] = '\0'; 42 getnext(s); 43 44 int flag = 1; 45 for(int k = 1; flag&&k < n; k++) 46 if(KMP(str[k], s)==-1) 47 flag = 0; 48 ///匹配成功,判长度和字典序 49 if(flag&& ( strlen(s)>strlen(ans) || ( strlen(s)==strlen(ans)&&strcmp(s, ans)<0))) 50 strcpy(ans, s); 51 } 52 53 if(strlen(ans) < 3) puts("no significant commonalities"); 54 else puts(ans); 55 } 56 return 0; 57 }
题目:POJ3461 http://poj.org/problem?id=3461
题意:求第一个串在第二个串中出现的次数
1 //第一个串在第二个串中出现的次数 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define MAXN 1000050 7 char s[MAXN],t[MAXN]; 8 int l1,l2; 9 int next[MAXN]; 10 void getnext(){ 11 int j=0,k=-1; 12 next[0]=-1; 13 while(j<l2){ 14 if(k==-1||t[j]==t[k]) next[++j]=++k; 15 else k=next[k]; 16 } 17 } 18 int kmpcount(){ 19 int ans=0,i=0,j=0; 20 getnext(); 21 while(i<l1){ 22 if(j==-1||s[i]==t[j]) 23 i++, j++; 24 else j=next[j]; 25 if(j==l2) 26 ans++, j=next[j]; 27 } 28 return ans; 29 } 30 int main(){ 31 int T; scanf("%d",&T); 32 while(T--){ 33 scanf("%s%s",t,s); 34 l1=strlen(s); 35 l2=strlen(t); 36 printf("%d\n",kmpcount()); 37 } 38 return 0; 39 }