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

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

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

代码:
 1 # include  < cstdio >
 2 # include  < cstring >
 3 using   namespace  std;
 4 char  str[ 101 ][ 105 ];
 5 int  n;
 6 void  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}

16 bool  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}

44 int  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

你可能感兴趣的:(pku 1226 Substrings 应该用后缀数组。。我二分+暴力的。。)