编程之美2015 资格赛 hihocoder 题目2: 回文字符序列

 

思路:暴力搜,用BFS的方式,生成每一种可能,再对每一种可能进行判断是否回文,进行统计。严重超时!计算一个25个字符的,大概要20多秒!

 1 #include <iostream>

 2 #include <deque>

 3 #include <string>

 4 #include <stdio.h>

 5 #include <cstring>

 6 using namespace std;

 7 

 8 deque<string> a;

 9 

10 bool isP(string &s )

11 {

12     string::iterator it1=s.begin();

13     string::iterator it2=s.end();

14     while( it1!=it2 && it1!=--it2 )

15     {

16         if( *it1!=*it2 )

17             return false;

18         it1++;

19     }

20     return true;

21 }

22 

23 unsigned long long count()   //判断回文,注意取余

24 {

25     unsigned long long cnt=0;

26     string tmp="";

27     a.pop_front();

28     while( !a.empty() )

29     {

30         tmp =a.front();

31 

32         if( tmp.size()==1 )

33             cnt++;  //单个的情况

34         else if( isP(tmp)==true )

35             cnt++;

36 

37         a.pop_front();

38         if(cnt>100007 )

39             cnt %= 100007;

40     }

41     return cnt;

42 }

43 

44 int betree(string &s, int len)  //生成树

45 {

46     string tmp="";

47     a.push_back(tmp);

48 

49     int i, j, limit =a.size() ;

50 

51     for(i=0; i<len; i++)

52     {

53         for(j=0; j<limit; j++)

54         {

55             a.push_back(a.front());   //不装第i个

56             a.push_back(a.front()+s[i]);   //装第i个

57             a.pop_front();

58         }

59         limit =a.size();

60     }

61     return 0;

62 }

63 

64 int main()

65 {

66     //freopen("input.txt","r",stdin);

67     int t, j=0;

68     string s;

69     cin>>t;

70     while(t--)

71     {

72         a.clear();

73         s="";

74         cin>>s;

75         betree(s, s.size());

76         cout<<"Case #"<< ++j<< ": "<< count()<<endl;

77     }

78     return 0;

79 }
BFS超时

 

 

另外的思路:肯定可以用DP。参考了别人的代码思路。添加了个SAO函数来记录当前字符在前面所出现的位置,若没出现过则置-1,这样可少扫很多次。

 1 #include <iostream>

 2 #include <string>

 3 #include <stdio.h>

 4 #include <memory>

 5 #include <string.h>

 6 using namespace std;

 7 long long map[1001][1001];

 8 int pos[26];

 9 int tmp[130];

10 int len;

11 string input;

12 void cal(int start ,int end)

13 {

14     if(start==end)      //自己到自己,即单个字符的情况,是回文,也就是它自己

15     {

16         map[start][end]=1;

17         return ;

18     }

19     if(end-start==1)    //两个字符的情况,判断两者是否相同。若相同,则有3个,否则,只有两个

20     {

21         if(input[start]==input[end])

22             map[start][end]=3;

23         else

24             map[start][end]=2;

25         return ;

26     }

27     map[start][end]+=map[start][end-1]+1;   //先加一个,也就是他自己单独作为回文串。

28 

29 /*

30     for(int i=end-1; i>=start; i--)

31     {

32         if(input[i]==input[end])            //考虑end之前的每一个,对于第i个,如果和end相同,那么结果就是i到end之间的串的回文串的最大数量+1

33             map[start][end] += map[i+1][end-1]+1;       //状态方程

34     }

35 */

36     int temp = pos[end];

37     while( temp>-1 && temp>=start )

38     {

39         map[start][end] += map[temp+1][end-1]+1;       //状态方程

40         temp = pos[temp];

41     }

42 

43     map[start][end]%=100007;

44 }

45 

46 void sao()

47 {

48     for(int i=0; i<26; i++)

49         pos[i] = -1;        // -1说明第1个字符的前面并没有与其相同的字符。

50     for(int i=0; i<130; i++)    //记录最近一个字符出现的位置

51         tmp[i] = -1;

52 

53     for(int i=0; i<len; i++)

54     {

55         pos[i] = tmp[input[i]];

56         tmp[input[i]] = i;       //更新字符input[i]最新出现的位置

57     }

58 }

59 

60 int main()

61 {

62     //freopen("input.txt","r",stdin);

63     int T;

64     int Case=0;

65     cin>>T;

66 

67     while(T--)

68     {

69         memset(map,0,sizeof(map));

70 

71         cin>>input;

72         len = input.size();

73         sao();

74         for(int i=0; i<input.size(); i++)   //从左往右扫

75         {

76             for(int j=i; j>=0; j--)         //从第i个开始往左扫,才能保证在计算大问题之前,所要依靠的小问题已经被解决

77             {

78                 cal(j,i);

79             }

80         }

81         cout<<"Case #"<<++Case<<": "<<map[0][input.size()-1]<<endl;

82     }

83 

84 }
AC了

 

你可能感兴趣的:(code)