Description
Marge: Yeah, what is it?
Homer: Take me for example. I want to find out if I have a talent in politics, OK?
Marge: OK.
Homer: So I take some politician’s name, say Clinton, and try to find the length of the longest prefix
in Clinton’s name that is a suffix in my name. That’s how close I am to being a politician like Clinton
Marge: Why on earth choose the longest prefix that is a suffix???
Homer: Well, our talents are deeply hidden within ourselves, Marge.
Marge: So how close are you?
Homer: 0!
Marge: I’m not surprised.
Homer: But you know, you must have some real math talent hidden deep in you.
Marge: How come?
Homer: Riemann and Marjorie gives 3!!!
Marge: Who the heck is Riemann?
Homer: Never mind.
Write a program that, when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.
Input
Output
The lengths of s1 and s2 will be at most 50000.
Sample Input
clinton homer riemann marjorie
Sample Output
0 rie 3
對話都是廢話,只看最後一句when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.馬上就想到把s2接到s1後面成爲一個新的字符串,然後找next[n]就完了,我看到很多博客還去找s1前綴和找s2的後綴,然後來匹配,感覺好麻煩。是我太機智(但是並沒有覺得想到這個方法很巧妙)還是他們太死板?
代碼:
#include<stdio.h>
#include<string.h>
#define MaxSize 500005
#define inf 0x3f3f3f3f
#define LL long long int
char s[2*MaxSize],s2[MaxSize];
int next[2*MaxSize];
int n;
void get_next()
{
int i=0;
int j=next[0]=-1;
while(i<n)
{
if(j==-1 || s[j]==s[i])
next[++i]=++j;
else j=next[j];
}
}
int main()
{
while(~scanf("%s%s",s,s2))
{
int len=strlen(s);
s[len]='A';
s[len+1]='\0';
/*爲了防止接在一起之後出現一種神奇的情況,中間必須加上一個字符隔開。比如s1:abca,s2:bcab,
正確答案應該是ab。但如果直接接到一起變成了abcabcab,相同前後綴就變成了abcab,這樣前綴都超過s1的長度明顯就不行了。
所以中間應加一個字母隔開防止越界(題上說了給的s1和s2只有小寫字母,於是我們就用大寫字母隔),
變成abcaAbcab,這樣就絕對不會出現前後綴越界的情況了*/
strcat(s,s2);
n=strlen(s);
get_next();
s[next[n]]='\0';//用for輸出%c多半會超時,這裏手動加個結束符,給出地址用%s輸出速度會快很多
printf("%s",s);
if(next[n]!=0) printf(" ");
printf("%d\n",next[n]);
}
return 0;
}
Description
親和串的定義是這樣的:給定兩個字符串s1和s2,如果能通過s1循環移位,使s2包含在s1中,那麼我們就說s2 是s1的親和串。
Input
Output
Sample Input
AABCD CDAA ASD ASDF
Sample Output
yes no
思路:
既然可以循環匹配,就把原串首尾連接。比如原串是abcd,我們就abcd+abc變成abcdabc,這樣循環問題就解決了。但是如果目標串是bcdab,這樣在連接後的新串裏面是找得到的,感覺是合法的。但是在原串中循環匹配的時候這是不合法的,因爲出現了後面又走到了b,已經開始重疊了。解決這個問題很簡單,判斷如果目標串長度大於原串,就一定找不到。要能在原串中循環匹配成功,長度必定是小於等於原串長度的。
代碼;
#include<stdio.h>
#include<string.h>
#define MaxSize 100005
#define inf 0x3f3f3f3f
#define LL long long int
char s[MaxSize],s1[2*MaxSize],s2[MaxSize];
int next[MaxSize];
int n,m;
void get_next()
{
int i=0;
int j=next[0]=-1;
while(i<m)
{
if(j==-1 || s2[i] == s2[j])
next[++i]=++j;
else
j=next[j];
}
}
void find()
{
int i=0;
int j=0;
while(i<n)
{
if(j==-1 || s1[i]==s2[j])
{
i++;
j++;
}
else
j=next[j];
if(j==m)
{
printf("yes\n");
return;
}
}
printf("no\n");
}
int main()
{
while(~scanf("%s%s",s,s2))
{
strcpy(s1,s);
strcat(s1,s);
n=strlen(s1)-1;
s1[n]='\0';
m=strlen(s2);
if(m > strlen(s))
{
printf("no\n");
continue;
}
get_next();
find();
}
return 0;
}
Description
Step1. Connect the father's name and the mother's name, to a new string S.
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).
Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)
Input
Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.
Output
Sample Input
ababcababababcabab aaaaa
Sample Output
2 4 9 18 1 2 3 4 5
思路:
這道題就是把所有的相同前後綴長度輸出來,就是把原來的只求最大next[n]變成了 求長度從0~next[n]的相同前後綴。於是在next[]求到最後一步的時候,對j=next[j]不斷進行迭代就行了。
代碼:
#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
using namespace std;
#define MaxSize 400005
int n;
int next[MaxSize];
char s[MaxSize];
void get_next()
{
int i=0;
int j=next[0]=-1;
stack<int>sta;
while(i<n)
{
if(j==-1 || s[i]==s[j])
{
next[++i] = ++j;
if(i==n)
{
i--;
j--;
while(j!=-1)
{
if(s[i]==s[j])
sta.push(j+1);
j=next[j];
}
while(!sta.empty())
{
printf("%d ",sta.top());
sta.pop();
}
printf("%d\n",n);
break;
}
}
else
j=next[j];
}
}
int main()
{
while(~scanf("%s",s))
{
n=strlen(s);
get_next();
}
return 0;
}
Description
Input
Output
Sample Input
abcd aaaa ababab .
Sample Output
1 4 3
遇到‘.’就停止,傻狍子出題人咋不寫出來,還以爲是不小心多打的句號,坑的一筆。這道題就是求字符串由多少個相同的最小cell組成,這個代碼的思路我想到過,但是不知道是不是真的可行,都準備放棄了,結果看了別人的博客真的可以這樣。
代碼:
#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
using namespace std;
#define MaxSize 1000005
char s[MaxSize];
short next[MaxSize];
int n;
void get_next()
{
int i=0;
int j=next[0]=-1;
while(i<n)
{
if(j==-1 || s[i]==s[j])
next[++i]=++j;
else
j=next[j];
}
//int len = n-next[n];//告訴你們一件可怕的事,這樣寫的要wa的。明明是和下面那句等價的,但是它就要wa,就是不知道爲什麼,真可怕。
int len = i-j;
if(n%len == 0)
printf("%d\n",n/len);
else
printf("1\n");
}
int main()
{
while(~scanf("%s",s) && strcmp(s,".")!=0)
{
n=strlen(s);
get_next();
}
return 0;
}