[关闭]
@morehigh 2017-02-25T03:19:04.000000Z 字数 3188 阅读 993

CQUPT 集训队专题训练(字符串)

字符串


A - 最小表示法 POJ - 1509
题意:

  1. 给出一个字符串首尾相连构成循环,求出以某哪个字母为起点,这个字符串的字典序最小

解题思路:

  1. 最小表示法维护两个指针,i=0(表示以此字母为起点时字典序最小),j=1(用来维护i指针,与i指向的字母进行比较),当S[i]>S[j]时,i=j,j=j+1;当S[i]<S[j],j++,当S[i]==S[j],设一个k指针,i,j一直向下比较,直到不想等 。如果S[i+k] > S[j+k] i=i+k,否则j++,返回ij的小者

代码:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <map>
  5. #include <string>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. char ss[10024];
  10. int main()
  11. {
  12. int n;
  13. scanf("%d",&n);
  14. while(n--)
  15. {
  16. scanf("%s",ss);
  17. int len=strlen(ss);
  18. int i=0,j=1,k=0;
  19. while(i<len&&j<len&&k<len)
  20. {
  21. int t=ss[(i+k)%len]-ss[(j+k)%len];
  22. if(!t)
  23. k++;
  24. else
  25. {
  26. t>0?i=i+k+1:j=j+k+1;
  27. if(i==j)
  28. j++;
  29. k=0;
  30. }
  31. }
  32. if(i<j)
  33. cout<<i+1<<endl;
  34. else
  35. cout<<j+1<<endl;
  36. }
  37. return 0;
  38. }
  39. B - KMP HDU - 1686
  40. 题意:

给出一个字符串W和一个字符串T,在T中有多少个W?

  1. 解题思路:

KMP,主要是那个nxt[i]辅助数组,表示看了几遍还是有点绕

  1. [http://www.ituring.com.cn/article/59881][1]
  2. 代码:

include

include

include

include

include

include

include

using namespace std;
int lenw,lent;
char w[100010],t[1000010];
int nxt[1000010];

void getnext()
{
nxt[0]=-1;
int j=1,i;
for(;j {
i=nxt[j-1];
while(w[i+1]!=w[j]&&i>=0) i=nxt[i];
if(w[i+1]==w[j]) nxt[j]=i+1;
else
nxt[j]=-1;
}
}
int kmp()
{
int j=0,i=-1;
int count=0;
for(;j {
while(w[i+1]!=t[j]&&i>=0) i=nxt[i];
if(w[i+1]==t[j]) i++;
if(i==lenw-1)
{
count++;
i=nxt[i];
}
}
return count;
}
int main()
{
int n;
int len,ans;
scanf("%d",&n);
while(n--)
{
scanf("%s%s",w,t);
lenw=strlen(w);
lent=strlen(t);
getnext();
ans=kmp();
printf("%d\n",ans);
}
return 0;
}
```
D - 字典树 HDU - 1251
题意:

  1. 输入数据的第一部分是一张单词表,统计出以某个字符串为前缀的单词数量。

解题思路:

  1. 第一种思路是用到stl里面的map,直接统计单词表中所有子串为前缀的数量,代码简单但是时间复杂度比较高,第二种就是直接建立一棵字典树,将字符串向下延伸,沿途的权值加一。

代码:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <map>
  5. #include <string>
  6. #include <vector>
  7. #include <queue>
  8. #include <malloc.h>
  9. #define maxn 26
  10. using namespace std;
  11. char str[15];
  12. map<string,int> mp;
  13. int main()
  14. {
  15. while(gets(str)&&str[0]!='\0'){
  16. int len=strlen(str);
  17. for(int i=len-1;i>=0;i--)
  18. {
  19. mp[str]++;
  20. str[i]='\0';
  21. }
  22. }
  23. while(gets(str))
  24. {
  25. cout<<mp[str]<<endl;
  26. }
  27. return 0;
  28. }
  29. #include <iostream>
  30. #include <cstdio>
  31. #include <cstring>
  32. #include <algorithm>
  33. using namespace std;
  34. int g[2000000][26]={0},tot;
  35. int rak[1000000]={0};
  36. char c='a';
  37. void init()
  38. {
  39. memset(g[1],0,sizeof(g[1]));
  40. tot=1;
  41. }
  42. void insert(char* s)
  43. {
  44. int i;
  45. for(i=1;*s;++s)
  46. {
  47. if(!g[i][*s-c])
  48. {
  49. i=g[i][*s-c]=++tot;
  50. rak[i]++;
  51. memset(g[tot],0,sizeof(g[tot]));
  52. }else
  53. {
  54. i=g[i][*s-c];
  55. rak[i]++;
  56. }
  57. }
  58. }
  59. int query(char* s)
  60. {
  61. int i;
  62. for(i=1;*s;++s)
  63. {
  64. if(!g[i][*s-c])return 0;
  65. i=g[i][*s-c];
  66. }
  67. return rak[i];
  68. }
  69. int main()
  70. {
  71. char str[20];
  72. init();
  73. while(gets(str),strlen(str)>0)
  74. {
  75. insert(str);
  76. }
  77. while(scanf("%s",str)!=EOF)
  78. {
  79. printf("%d\n",query(str));
  80. }
  81. return 0;
  82. }

E - Manacher POJ - 3974
题意:

  1. 给出一串字符串,字符串的长度不长于1000000 ,求出最长的回文子串。

解题思路:

  1. 先对字符串进行一次性处理,将两个字符之间加上#,使得奇回文串和偶回文串统一在一起考虑,辅助数组Pid]记录的是以字符strid]为中心的最长回文串,当以strid]为第一个字符,这个最长回文串向右延伸了Pid]个字符。

http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/

代码:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <map>
  5. #include <string>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. int len,cas;
  10. char ss[1000010],s1[3000010];
  11. int p[3000010];
  12. void solve()
  13. {
  14. int mx=0;
  15. int id,ans=1;
  16. for(int i=1;i<=len;i++)
  17. {
  18. if(mx>i)
  19. p[i]=min(p[2*id-i],mx-i);
  20. else
  21. p[i]=1;
  22. for(;s1[i+p[i]]==s1[i-p[i]];p[i]++);
  23. if(i+p[i]>mx)
  24. {
  25. mx=p[i]+i;
  26. id=i;
  27. }
  28. ans=max(ans,p[i]);
  29. }
  30. printf("Case %d: %d\n",cas++,ans-1);
  31. }
  32. int main()
  33. {
  34. cas=1;
  35. while(scanf("%s",ss)!=-1)
  36. {
  37. if(strcmp(ss,"END")==0)
  38. break;
  39. len=strlen(ss);
  40. s1[0]='@';
  41. s1[1]='#';
  42. int i;
  43. for(i=0;i<len;i++)
  44. {
  45. s1[2*i+2]=ss[i];
  46. s1[2*i+3]='#';
  47. }
  48. len=2*i+3;
  49. solve();
  50. }
  51. return 0;
  52. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注