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;
}