码迷,mamicode.com
首页 > 其他好文 > 详细

[2016-05-04][codeforces][666A - Reberland Linguistics]

时间:2016-05-04 18:41:57      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:

  • 时间:2016-05-04 16:51:34 星期三

  • 题目编号:[2016-05-04][codeforces][666A - Reberland Linguistics]

  • 题目大意:一个单词由长度不少于5的词根和长度为2或3的若干个后缀组成,并且两个相邻的后缀不能一样,给定一个单词,问这个单词总共可以有多少个后缀

  • 分析:

    • 类似dp 的思想,dp[i] 表示第i个位置到字符串结束能否划分成合法后缀,
    • 那么dp[i] = dp[i +t] ∧ ( dp[i + 5] ∨ 子串(i,t) != 子串 (i + t , t)); t == 2 或 3
    • 即,从后往前扫,每增加一个字符,就判断由它开始的长度为2 和 3的后缀 和剩下部分 组成的后缀 是否合法
    • 新后缀是否合法,
      • 使用这个后缀后,剩下部分仍然能正常分割成2 或 3的若干个后缀
      • 这个后缀和下一个那个后缀不一样(只要存在不一样的分法就可以)
        • 这个后缀和下一个后缀长度一样:直接比较
        • 长度不一样,显然成立,但是要在往前数5位剩下的能合法分割,即dp[I+ 5]为真的情况才行
  • 遇到的问题:

    • 判断当前后缀和下一个后缀是否一样的时候,如果用子串来比较的话,刚开始的时候,i + 2 > 长度 的时候会出错
    • 解决办法是,不生成子串,而是通过find函数,来查找下一个和它相同的字符串的位置
    • 初始化 dp[长度] = 0;
  1. #include<iostream>
  2. #include<string>
  3. #include<set>
  4. #include<cstring>
  5. using namespace std;
  6. set<string> s;
  7. const int maxn = 1E4 + 10 ;
  8. int dp[maxn];
  9. int main(){
  10. string str;
  11. cin>>str;
  12. memset(dp,0,sizeof(dp));
  13. str = str.substr(5);
  14. int n = str.length();
  15. string tmp;
  16. dp[n] = 1;
  17. for(int i = n - 1; i >= 0 ; --i){
  18. for(int l = 2 ; l <= 3 ; ++l){
  19. tmp = str.substr(i, l);
  20. if(( str.find(tmp,i + l) != i + l || dp[i + 5] ) && dp[i + l] ){
  21. s.insert(tmp);
  22. dp[i] = 1;
  23. }
  24. }
  25. }
  26. cout<<s.size()<<"\n";
  27. for(set<string>::iterator its = s.begin(); its != s.end();++its){
  28. cout<<*its<<"\n";
  29. }
  30. return 0;
  31. }




[2016-05-04][codeforces][666A - Reberland Linguistics]

标签:

原文地址:http://www.cnblogs.com/qhy285571052/p/d51cf80b94c4caf676fa33aef57096e0.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!