[关闭]
@iamtts 2017-02-18T11:39:45.000000Z 字数 2350 阅读 985

寒假第八次训练-字符串

A - 最小表示法

题目大意:给一堆字符串,针对每个字符串问字典序最小的一种串(和圆圈一样任意起点)的首字母序号。

解题思路:朴素算法的话复杂度很高,用最小表示法,若a[i]>a[j]则将i移动至更小的字母处,小于则不处理,相等的话直到a[i+k]!=a[j+k],若a[i+k]>a[j+k]则i=i+k+1,否则j=j+k+1。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. #include <queue>
  10. #include <cmath>
  11. #include <sstream>
  12. using namespace std;
  13. #define MAXN 10005
  14. char s[MAXN];
  15. int mp(char *s)
  16. {
  17. int i=0,j=1,k=0,l=strlen(s),t;
  18. while (i<l && j<l && k<l)
  19. {
  20. t=s[(i+k)%l]-s[(j+k)%l];
  21. if (!t) k++;
  22. else
  23. {
  24. if (t>0) i=i+k+1;
  25. else j=j+k+1;
  26. if (i==j) j++;
  27. k=0;
  28. }
  29. }
  30. return min(i,j);
  31. }
  32. int main()
  33. {
  34. int i,t;
  35. //FILE *fp;
  36. //fp=fopen("output.txt","w");
  37. scanf("%d",&t);
  38. while (t--)
  39. {
  40. scanf("%s",s);
  41. printf("%d\n",mp(s)+1);
  42. }
  43. //fclose(fp);
  44. }

B - KMP

题目大意:给字符串A,B,问在B中匹配了多少次A。

解题思路:裸KMP

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. #include <queue>
  10. #include <cmath>
  11. #include <sstream>
  12. using namespace std;
  13. #define MAXN 10005
  14. char s[10005],raw[1000005];
  15. int Next[10010];
  16. void get_Next()
  17. {
  18. int i,j,l=strlen(s);
  19. Next[0]=Next[1]=0;
  20. for (i=1; i<=l; i++)
  21. {
  22. int j=Next[i];
  23. while (j && s[i]!=s[j]) j=Next[j];
  24. Next[i+1]=s[i]==s[j]?j+1:0;
  25. }
  26. }
  27. int KMP()
  28. {
  29. int i,l2=strlen(raw),l1=strlen(s),cnt=0,j=0;
  30. for (i=0;i<l2;i++)
  31. {
  32. while(j && s[j]!=raw[i]) j=Next[j];
  33. if (s[j]==raw[i]) j++;
  34. if (j==l1) cnt++;
  35. }
  36. return cnt;
  37. }
  38. int main()
  39. {
  40. int t;
  41. scanf("%d",&t);
  42. while (t--)
  43. {
  44. scanf("%s",s);
  45. scanf("%s",raw);
  46. get_Next();
  47. //for (int i=1;i<=strlen(s);i++) printf("%d ",Next[i]);
  48. printf("%d\n",KMP());
  49. }
  50. }

D - 字典树

题目大意:给一堆单词和一堆前缀,针对每个前缀,问以该前缀为前缀的单词有多少

解题思路:裸字典树,每个节点计数。应为空间足够所以没有释放空间。

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <vector>
  7. #include <cstring>
  8. #include <stack>
  9. #include <queue>
  10. #include <cmath>
  11. #include <sstream>
  12. using namespace std;
  13. #define MAXN 1024+10
  14. char s[15];
  15. int cnt;
  16. struct tree
  17. {
  18. tree *next[26];
  19. int v;
  20. };
  21. tree *root;
  22. void create_tree(char *s)
  23. {
  24. int l=strlen(s),i;
  25. tree *p=root;
  26. for (i=0; i<l; i++)
  27. {
  28. int id=s[i]-'a';
  29. if (p->next[id]==NULL)
  30. {
  31. tree *q=new tree;
  32. for (int j=0; j<26; j++) q->next[j]=NULL;
  33. p->next[id]=q;
  34. q->v=1;
  35. p=q;
  36. }
  37. else {p->next[id]->v++;p=p->next[id];}
  38. }
  39. }
  40. void find_prefix(char *s)
  41. {
  42. int l=strlen(s);
  43. tree *p=root;
  44. for (int i=0;i<l;i++)
  45. {
  46. int id=s[i]-'a';
  47. p=p->next[id];
  48. if (p==NULL) {cnt=0;return;}
  49. if (p->v) cnt=p->v;
  50. }
  51. }
  52. int main()
  53. {
  54. root=new tree;
  55. for (int j=0; j<26; j++) {root->next[j]=NULL;}
  56. root->v=0;
  57. while (cin.getline(s,15),strlen(s))
  58. {
  59. create_tree(s);
  60. }
  61. while (~scanf("%s",s))
  62. {
  63. cnt=0;
  64. find_prefix(s);
  65. printf("%d\n",cnt);
  66. }
  67. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注