第一题 hdu 1711 Number Sequence
题意:就是匹配看在不在。
第二题 hdu 1686 oulipo
点击打开hdu 1686
思路:
1 题目要求的是给定一个模式串个一个文本串,求出模式串在文本串中出现几次
第三题 hdu 2087 剪花布条
点击打开hdu 2087
思路:
1 题目要求的是给定一个文本串和给定一个模式串,求文本串中有几个模式串。
2 注意文本串为”aaaaaa”,模式串”aa”的时候,ans = 3 而不是5。(与上面一题不同)
第四题 hdu 3746 Cyclic Nacklace
点击打开hdu 3746
思路:(最小循环节个数+注意当为abcd的时候。。
1 题目要求的是给定一个字符串,问我们还需要添加几个字符可以构成一个由n个循环节组成的字符串。
2 可知我们应该先求出字符串的最小循环节的长度:假设字符串的长度为len,那么最小的循环节就是cir = len-next[len] ; 如果有len%cir == 0,那么这个字符串就是已经是完美的字符串,不用添加任何字符;如果不是完美的那么需要添加的字符数就是cir - (len-(len/cir)*cir)),相当与需要在最后一个循环节上面添加几个。
3 如果cir = 1,说明字符串只有一种字符例如“aaa” ; 如果cir = m说明最小的循环节长度为m,那么至少还需m个;
如果m%cir == 0,说明已经不用添加了
点击查看代码
第五题 hdu 1358 Period
点击打开hdu 1358
思路:
1 题目要求的是给定一个长度为n的字符串,求出字符串的所有前缀字符串中该字符串刚好由k个最小循环节够成,由于题目要求k最大那么就是这个循环节最小
2 只要先求出next数组,然后去枚举所有的前缀找到满足的输出长度和k注意当为abcd的时候。。
点击查看代码
第六题 hdu 2203 亲和串
点击打开hdu 2203
思路:
1 题目要求的是给定字符串s1 和 s2,问s1能否通过移位得到使得s2包含在s1里面。
2 很显然的kmp的模板题,只须在s1后面在添上一个s1即可。这里特别注意strcat的使用
第七题 hust 1010 The Minimum Length
点击打开hust 1010
思路:
1 题目要求的是,有一个字串A,现在利用A组成了一个新的字符串AAAAA…,现在从这个新的字符串的两个不同位置剪下去得到字符串B,问A的最小长度
2 由于B里面的字符都是来自A,那么如果要A最小那么最小值就是等于B的最小循环节。
3 直接对B求最小循环节(比如baaabbba, 答案也是6,说明
baaabbba
baaabbba 中baaabb就是最小循环节
第八题 poj 2406 Power Strings
点击打开poj 2406
思路:
1 题目要求的是给定一个字符串找到最小循环节的个数,但是这里有个限制的地方就是如果这个字符串
不是刚好由n个最小循环节组成那么就认为一整串才是一个循环节(这个地方对于不同的题目不同)
2 题目说了输入的字符是可打印的,所以应该用gets读入,判断终止的时候用strcmp。
点击查看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
const int maxn=1e6+5;
char a[maxn];
int nxt[maxn];
void getnxt(){
int k=-1;
int j=0;
nxt[0]=-1;
int len=strlen(a);
while(j<len){
if(k==-1||a[k]==a[j]){
k++;
j++;
nxt[j]=k;
}
else k=nxt[k];
}
}
void init(){
//memset(dp,0,sizeof(dp));
memset(nxt,0,sizeof(nxt));
}
int main(){
int n;
int cnt=0;
while(~scanf("%d",&n)&&n!=0){
init();
scanf("%s",&a);
getnxt();
printf("Test case #%d\n",++cnt);
for(int i=2;i<=n;++i){
int cir=i-nxt[i];
if(cir==1)printf("%d %d\n",i,i);//
else if(cir!=i&&i%cir==0){//自己这些地方太简陋了导致错误
//如果cir=i,那么就是他自己没有循环节的。比如asdf,我原本的结果也会输出
cout<<i<<' '<<i/cir<<'\n';
}
else continue;
}
cout<<'\n';
}
}
原本代码:
int cir=i-nxt[i];
if(i%cir==0){
cout<<i<<' '<<i/cir<<'\n';
}
else continue;
思路:
1 题目要求的是给定字符串s1 和 s2,问s1能否通过移位得到使得s2包含在s1里面。
2 很显然的kmp的模板题,只须在s1后面在添上一个s1即可。(我居然没有想到。。)这里特别注意strcat的使用
3 strcat函数,函数的原行strcat(char *s , char *p);注意这里的s和p所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串;所以假设s = “abc”,现在想得到“abcabc”那么不能直接的strcat(s , s),而是先用一个tmp数组存储s,即strcpy(tmp , s , sizeof(s)) , 然后在strcat(s , tmp);