例题1链接:点击打开链接
原题:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 24044 | Accepted: 9633 |
Description
The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:
Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal, d’abord, puis surgissait l’inhumain, l’affolant. Il aurait voulu savoir où s’articulait l’association qui l’unissait au roman : stir son tapis, assaillant à tout instant son imagination, l’intuition d’un tabou, la vision d’un mal obscur, d’un quoi vacant, d’un non-dit : la vision, l’avision d’un oubli commandant tout, où s’abolissait la raison : tout avait l’air normal mais…
Perec would probably have scored high (or rather, low) in the following contest. People are asked to write a perhaps even meaningful text on some subject with as few occurrences of a given “word” as possible. Our task is to provide the jury with a program that counts these occurrences, in order to obtain a ranking of the competitors. These competitors often write very long texts with nonsense meaning; a sequence of 500,000 consecutive 'T's is not unusual. And they never use spaces.
So we want to quickly find out how often a word, i.e., a given string, occurs in a text. More formally: given the alphabet {'A', 'B', 'C', …, 'Z'} and two finite strings over that alphabet, a word W and a textT, count the number of occurrences of W in T. All the consecutive characters of W must exactly match consecutive characters of T. Occurrences may overlap.
Input
The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:
Output
For every test case in the input file, the output should contain a single number, on a single line: the number of occurrences of the word W in the text T.
Sample Input
3 BAPC BAPC AZA AZAZAZA VERDI AVERDXIVYERDIAN
Sample Output
1 3 0
Source
AC code:
#include<stdio.h>
#include<string.h>}
提取模板:
void Get_next()
{
int i=0,j=-1;
next[0]=-1;
while(i<=Tlen)
{
if(j==-1||chT[i]==chT[j])
{
i++; j++;
next[i]=j;
}
else
j=next[j];
}
}
int Kmp(int u)
{
int i=u-1,j=-1,m=0; //字符串从0开始存储的
while(i<=TTlen)
{
if(j==-1||ch[i]==chT[j])
{
i++; j++;
}
else
j=next[j];
if(j>=Tlen) //**注意这里要j--,i++,因为上面匹配成功了i和j的值加多了1
{
m++;
j--; i--;
j=next[j]; //返回
}
}
return m;
}
例题2链接:点击打开链接
原题:
5 xy abc aaa aaaaba aaxoaaaaa
0 0 1 1 2
AC code:
#include<stdio.h>
#include<string.h>
char s[1111111];
int next[1111111],len,ans[1111111];
void get()
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=len)
{
if(j==-1||s[j]==s[i])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int i,j,k,cas,fg;
while(scanf("%d",&cas)!=EOF)
{
while(cas--)
{
scanf("%s",s);
len=strlen(s);
get();
ans[0]=len;
i=0;j=len;
while(next[j]>0)
{
ans[++i]=next[j];
j=next[j];
}
fg=0;
for(j=0;j<=i;j++)
{
if(ans[j]>len/3)
continue;
else
{
for(k=2*ans[j];k<=len-ans[j];k++)
{
if(next[k]==ans[j])
{
fg=1;
printf("%d\n",ans[j]);
break;
}
}
}
if(fg)
break;
}
if(fg==0)
printf("0\n");
}
}
return 0;
}
提取模板:
void Get_next() //求字符串的next[]前缀数组
{
int i=0,j=-1;
next[0]=-1;
while(i<=Tlen)
{
if(j==-1||ch[i]==ch[j])
{
i++; j++;
next[i]=j;
}
else
j=next[j];
}
}
例题3链接:点击打开链接
原题:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12324 | Accepted: 5355 |
Description
Input
Output
Sample Input
3 2 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 3 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA 3 CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Sample Output
no significant commonalities AGATAC CATCATCAT
Source
例题4链接:点击打开链接
原题:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 5078 | Accepted: 1885 |
Description
Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently asked ACM for a help with their new identity. IBM do not want to change their existing logos and trademarks completely, because their customers are used to the old ones. Therefore, ACM will only change existing trademarks instead of creating new ones.
After several other proposals, it was decided to take all existing trademarks and find the longest common sequence of letters that is contained in all of them. This sequence will be graphically emphasized to form a new logo. Then, the old trademarks may still be used while showing the new identity.
Your task is to find such a sequence.
Input
The input contains several tasks. Each task begins with a line containing a positive integer N, the number of trademarks (2 ≤ N ≤ 4000). The number is followed by N lines, each containing one trademark. Trademarks will be composed only from lowercase letters, the length of each trademark will be at least 1 and at most 200 characters.
After the last trademark, the next task begins. The last task is followed by a line containing zero.
Output
For each task, output a single line containing the longest string contained as a substring in all trademarks. If there are several strings of the same length, print the one that is lexicographically smallest. If there is no such non-empty string, output the words “IDENTITY LOST” instead.
Sample Input
3 aabbaabb abbababb bbbbbabb 2 xyz abc 0
Sample Output
abb IDENTITY LOST
Source
AC code:
#include<stdio.h>
#include<string.h>
char s[4001][201],s1[201],ans[201];
int next[201],lens[4001];
void get(char p[],int lenp)
{
int i,j;
i=0;
next[0]=-1;
j=-1;
while(i<=lenp)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(char t[],int lent,char p[],int lenp)
{
get(p,lenp);
int i,j,start;
i=-1;j=-1;start=-1;
while(i<=lent)
{
if(j==-1||p[j]==t[i])
{
i++;
j++;
}
else
j=next[j];
if(j==lenp)
{
start=i-lenp+1;
break;
}
}
return start;
}
int main()
{
int n,i,j,k,m,minlen,mini,cnt,st,maxlen;
while(scanf("%d",&n)!=EOF&&n)
{
minlen=300;
for(i=1;i<=n;i++)
{
scanf("%s",&s[i]);
lens[i]=strlen(s[i]);
if(minlen>lens[i])
{
minlen=lens[i];
mini=i;
}
}
maxlen=0;
for(i=0;i<=minlen-2;i++)
{
for(j=1;j<=minlen-i;j++)
{
if(minlen-j-i+1<maxlen)
break;
cnt=0;
for(k=i;k<=minlen-j;k++)
{
s1[cnt++]=s[mini][k];
}
s1[cnt]='\0';
for(m=1;m<=n;m++)
{
if(m==mini)
continue;
st=kmp(s[m],lens[m],s1,cnt);
if(st==-1)
break;
}
if(m==n+1)
{
if(maxlen==cnt)
{
if(strcmp(ans,s1)>0)
strcpy(ans,s1);
}
if(maxlen<cnt)
{
maxlen=cnt;
strcpy(ans,s1);
}
}
}
}
if(maxlen==0)
printf("IDENTITY LOST\n");
else
puts(ans);
}
return 0;
}
例题5链接:点击打开链接
原题:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 32616 | Accepted: 13602 |
Description
Input
Output
Sample Input
abcd aaaa ababab .
Sample Output
1 4 3
Hint
Source
该题代码和分析转自网址:http://blog.csdn.net/qq7366020/article/details/12968747
题目大意: 给出一个由某个串重复有限次得到的字符串
求重复次数最多是多少,既找出最小重复子串
解题思路: 字符串abcabcabc的next[ ]值为
0 1 2 3 4 5 6 7 8 9
a b c a b c a b c
-1 0 0 0 1 2 3 4 5 6
假设主串为abcabcabcX,模式串为abcabcabcK,Kmp的匹配过程
匹配到第10个字符发现不符:
a b c a b c a b c X
a b c a b c a b c K
不符合,j=next[j]
a b c a b c a b c X
a b c a b c a b c K
不符合,j=next[j]
a b c a b c a b c X
a b c a b c a b c K;
由next数组的定义可得: S[0-2]=S[3-5]=S[6-8]
当且仅当len%(len-next[len])=0时,len-next[len]是字符串的最小循环节
代码:
原题:
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 13365 | Accepted: 6296 |
Description
Input
Output
Sample Input
3 aaa 12 aabaabaabaab 0
Sample Output
Test case #1 2 2 3 3 Test case #2 2 2 6 2 9 3 12 4
Source
code:
#include<stdio.h>
#include<string.h>
char s[1000111];
int next[1000111],ans[1000111];
void get(char p[],int lenp)
{
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
for(i=1;i<=lenp-1;i++)
{
if((i+1)%(i+1-next[i+1])==0&&(i+1)!=(i+1-next[i+1]))//由于不输出1
printf("%d %d\n",i+1,(i+1)/(i+1-next[i+1]));
}
}
int main()
{
int len,n,cas;
cas=0;
while(scanf("%d",&n)!=EOF&&n)
{
cas++;
scanf("%s",s);
len=strlen(s);
printf("Test case #%d\n",cas);
get(s,len);
printf("\n");
}
return 0;
}
例题7链接:http://poj.org/problem?id=2752
原题:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 12266 | Accepted: 6032 |
Description
Input
Output
Sample Input
ababcababababcabab aaaaa
Sample Output
2 4 9 18 1 2 3 4 5
Source
大意:
给出一个字符串A,求A有多少个前缀同时也是后缀,从小到大输出这些前缀的长度。
分析:KMP
对于长度为len的字符串,由next的定义知:
A[0]A[1]...A[next[len]-1]=A[len-next[len]]...A[len-1]此时A[0]A[1]...A[next[len]-1]为一个符合条件的前缀
有A[0]A[1]....A[next[next[len]]-1] = A[len-next[next[len] - next[next[len]]]...A[next[len]-1],故A[0]A[1]....A[next[next[len]]-1]也是一个符合条件的前缀
故从len=>next[len]=>next[next[len]] ....=>直到某个next[]为0均为合法答案,注意当首位单词相同时,也为答案。
code:
#include<string.h>
#include<stdio.h>
char s[400111];
int next[400111],ans[400111],len;
void get(char p[],int lenp)
{
int i,j;
i=0;j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int n,cnt,i;
while(scanf("%s",s)!=EOF)
{
len=strlen(s);
get(s,len);
ans[1]=len;
cnt=1;
n=next[len];
while(n)
{
cnt++;
ans[cnt]=n;
n=next[n];
}
for(i=cnt;i>=1;i--)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}
解题思路分析亦可参考网址:http://www.doc88.com/p-997525236064.html
例题8链接:点击打开链接
原题:
3 aaa abca abcde
0 2 5
code:
#include<stdio.h>
#include<string.h>
char s[100111];
int next[100111],len;
void get(char p[],int lenp)
{
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<=lenp)
{
if(j==-1||p[j]==p[i])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
while(n--)
{
scanf("%s",s);
len=strlen(s);
get(s,len);
if(len%(len-next[len])==0)
{
if(next[len]==0)//相当于len/(len-next[len])==1的情况
printf("%d\n",len);
else
printf("0\n");
}
else
{
i=len%(len-next[len])-1;
j=len-1;
while(i>=0)
{
if(s[i]==s[j])
{
i--;
j--;
}
else
break;
}
if(i==-1)
printf("%d\n",len-next[len]-len%(len-next[len]));
else
printf("%d\n",len);
}
}
}
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题目反思与总结:
当所给字符串中无循环节时,如abcdeab , 我们求出其next数组的对应值(注意按照标准的next数组要多求一位,计算时向后推一位计算,因为标准的next数组第n个数表示的是第n-1个字符的匹配情况),然后用字符串长度L-next[L]即可,此时上例中显然next[L]为2,即为多出的ab,所以循环节就是7-2=5;
当所给字符串中有多个字符串时,如abxabxabxab,此时next[L]为8,11-8=3,亦是循环节,我们可以看出L-next[L]就是循环节,其实在一个多个循环节的字符串中,除了第一个循环节中字符外,其他每个位置的下标n-next[n]都是循环节(第一个循环节中的最后一个位置也可)。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------