题目描述
农夫约翰最近想发一些秘密的信息,但是他不想让奶牛们知道。这些信息是‘A’到’Z’的字符组成的,长度至少是2。
为了对这些信息进行加密,农夫约翰对这些信息进行了一系列的操作,每次操作,约翰把字符串S去掉从第一个开始连续的若干个字符或者从最后一个字符开始连续若干个字符(至少去掉一个字符,也不能全部去掉),然后把剩余的字符串添加到原来S串的左边或者右边。例如,对于字符串ABC,一次操作可以有8种结果:
AABC
ABABC
BCABC
CABC
ABCA
ABCAB
ABCBC
ABCC
现在给定最后加密好的字符串,约翰想要知道这个字符串可能由多少种方法加密而来,注意,AAA可以由AA通过四种加密操作得来,虽然产生的AAA是一样的,但是加密的过程是不一样的我们就认为是不同的方法。
输入
一个字符串。
输出
输出这个加密的字符串可以由多少种方法加密而来。【答案要mod 2014】
样例输入
ABABA
样例输出
8
分析:
这道题实际上是深搜+复制字符串的判断
我们可以得知我们截取的字符串,会在“原串”中有对应的字符串,如果存在,那么它必然在左边或者右边。
再具体细判左右,接着处理。
C++自带函数substr()可以很好的应用到这道题里。
CODE:
#include<string>
#include<iostream>
#include<algorithm>
#include<map>
#include<cstdio>
using namespace std;
map<string,int>g; //用个stl的map
string str;
int dfs(string str)
{
if(g[str]) return g[str]; //如果已经知道了g[str]的方案数,则可以退出
int ans=0,len=str.size(); //len长度
for(int i=0;(i+1)*2<len;i++)//因为字符串str最短为2,并且不能循环超过中间的字符(可以假设中间的字符是一个“原串”)
{
string a=str.substr(0,i+1);
string b=str.substr(i+1,i+1);
string c=str.substr(len-i-1,i+1);
string d=str.substr(len-i-i-2,i+1); //substr函数是复制字符串函数,前参数是起始位,后参数是长度
string e=str.substr(i+1,len-i-1);
string f=str.substr(0,len-i-1);
if(a==b) ans+=dfs(e);
if(a==c) ans+=dfs(e);
if(c==a) ans+=dfs(f);
if(c==d) ans+=dfs(f);
}
if(len>=2) ans++;
ans=ans%2014; //取模
g[str]=ans; //g[str]的方案数为ans
return ans;
}
int main()
{
freopen("scode.in","r",stdin);
freopen("scode.out","w",stdout);
cin>>str;
cout<<dfs(str)-1;
}