pku 1226 Substrings 应该用后缀数组。。我二分+暴力的。。

题意:
给出一堆字符串,设X为一个字符串,其本身或者其反转传在每个字符串中均出现。问x的最长长度。
解法:
由于数据小,100个字符串,最大长度为100,我就用了二分+暴力枚举验证。。
二分字符串长度,然后枚举其中一个字符串的起始位置s,验证以s为起始,长度为len的字符串(或其反转串)是否在所有字符串中都出现(这步复杂度o(n3))
加上二分的复杂度,总复杂度为o(n3logn)
正解应该是用后缀数组+二分。将所有原串和原串的反串连接起来计算后缀数组,二分子串长度,然后用height数组分类来验证。。复杂度o(n2logn)

代码:
 1# include <cstdio>
 2# include <cstring>
 3using namespace std;
 4char str[101][105];
 5int n;
 6void strreverse(char *str)
 7{
 8   int len=strlen(str);
 9   for(int i=0;i<len/2;i++)
10   {
11      char tmp=str[i];
12      str[i]=str[len-1-i];
13      str[len-1-i]=tmp;
14   }

15}

16bool chk(int len,int pos)
17{
18   for(int s=0;s+len<=strlen(str[pos]);s++)
19   {
20      char tmp=str[pos][s+len];
21      bool flag=true;
22      str[pos][s+len]='\0';
23      for(int j=0;j<n;j++)
24      {
25         if(strstr(str[j],str[pos]+s)) continue;
26         else
27         {
28             strreverse(str[pos]+s);
29             char *p=strstr(str[j],str[pos]+s);
30             strreverse(str[pos]+s);
31             if(!p)
32             {
33               flag=false;
34               break;
35             }

36         }

37      }

38      str[pos][s+len]=tmp;
39      if(flag) return true;
40      
41   }

42   return false;
43}

44int main()
45{
46   int test;
47   scanf("%d",&test);
48   while(test--)
49   {
50      int s=0,e=0xfffffff,pos;
51      scanf("%d",&n);
52      for(int i=0;i<n;i++)
53      {
54        scanf("%s",str[i]);
55        if(strlen(str[i])<e) e=strlen(str[i]),pos=i;
56      }

57      while(s<=e)
58      {
59         int mid=(s+e)>>1;
60         if(chk(mid,pos)) s=mid+1;
61         else e=mid-1;
62      }

63      printf("%d\n",s-1);
64   }

65   return 0;
66}

67
68

posted on 2010-12-09 21:09 yzhw 阅读(200) 评论(0)  编辑 收藏 引用 所属分类: string algorithm


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜