现在的位置: 首页 > 综合 > 正文

HDU 3336 Count the string (记忆化搜索)

2013年10月07日 ⁄ 综合 ⁄ 共 798字 ⁄ 字号 评论关闭

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);
	}
}

 

抱歉!评论已关闭.