http://acm.hdu.edu.cn/showproblem.php?pid=3336
題意:給定一個長度爲n的字符串(0<n<20000),以n的前k個字符組成一個前序(k = 1,2,3,4.....n),在n中找與前序相同的子序列的個數。
所謂的記憶化搜索,是因爲前一次的搜索對後面的搜索有幫助,就記錄下來,這樣可以減少後面搜索的時間。
看看樣例:
abab
前序是 a,ab,aba,abab
建立一個num數組,記錄每一個與前序相同的字串的頭下標。
a | b | a | b | |
a | 0 | 2 | ||
ab | 0 | 2 | ||
aba | 0 | |||
abab | 0 |
num[0] | num[1] | num[2] | num[3] | |
a | 0 | 2 | ||
ab | 0 | 2 | ||
aba | 0 | |||
abab | 0 |
因爲只有想要與一個前序相同,必先要與上一個前序相同,所以每次只要比較前序最後的一個元素是否與下標爲num[k]加上前序長度的元素相同就可以了。
#include <stdio.h>
int main ()
{
int t,n,i,j,k,sum,all,len;//len是記錄前序長度的
char ch[200010],ch1,ch2;
int num[200020],nn;//nn是記錄num數組中元素的個數,每比較完一次元素就更新一次
scanf ("%d",&t);
while (t-- > 0)
{
len = 0;
scanf ("%d%c",&n,&ch2);
gets(ch);
for (i = 0 ; i < n ; i ++)
num[i] = i ;
nn = n;
sum = 0;
for (i = 0 ; i < n ; i ++)
{
ch1 = ch[i];
int ji = 0;
for (j = 0 ; j < nn ; j ++)
{
if (num[j] + len < n && ch1 == ch[num[j] + len] && num[j] + len < n)
{
sum ++;
sum = sum % 10007 ;
num[ji ++] = num[j];
}
}
nn = ji;
len ++;
}
printf ("%d\n",sum);
}
}