HDU 1238 (暴力反转KMP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1238

题意:给定n个字符串,求它们的最长连续子序列,值得注意的是,求的的子序列可以是反转的。

题解:直接记录出最短的字符串作为匹配串,其实用第一个也应该是可以的,然后不断的缩小其长度,知道能够匹配成功,如果匹配不成功,则把字符串反转,再找一次即可。

Time:31ms

Memory:1712KB

reverse(s,s+n):字符串反转函数。

代码如下:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn = 105;
  7 char s[maxn][maxn];
  8 char t[maxn],f[maxn];
  9 int Next[maxn];
 10 void getcha(int len,int pos,char *s1)
 11 {
 12     for(int i=0,j=pos;i<len;i++,j++)
 13     {
 14         t[i]=s1[j];
 15     }
 16 //    cout<<t<<endl;
 17 }
 18 void getNext(int len)
 19 {
 20     int i=0,j=-1;
 21     Next[0]=-1;
 22     while(i<len)
 23     {
 24         if(j==-1||t[i]==t[j])
 25             i++,j++,Next[i]=j;
 26         else
 27             j=Next[j];
 28     }
 29 }
 30 int find(char *s1, int len1,int len2)
 31 {
 32     int i=0,j=0;
 33     while(i<len1&&j<len2)
 34     {
 35         if(j==-1||s1[i]==t[j])
 36         i++,j++;
 37         else
 38         j=Next[j];
 39         if(j==len2)
 40             return 1;
 41     }
 42     return 0;
 43 }
 44 int main()
 45 {
 46     int test;
 47     cin>>test;
 48     while(test--)
 49     {
 50         int leni[maxn]; //统计所有字符串的长度
 51         int n,len=200,te=0;
 52         scanf("%d",&n);
 53         for(int i=0;i<n;i++)
 54         {
 55             scanf("%s",s[i]);
 56             if(strlen(s[i])<len) //找出最短的字符串
 57             {
 58                 len=strlen(s[i]);
 59                 te = i;
 60             }
 61         }
 62         for(int i=0;i<n;i++)
 63             leni[i]=strlen(s[i]);
 64         int temp1=0,temp2=-1; //temp1用来标记该长度是否可以全部匹配,temp2用来记录长度。
 65         for(int i=len;i>0;i--)//代表所需子串的长度
 66         {
 67             memset(t,0,sizeof(t));
 68             for(int j=len-i;j>=0;j--)//该长度的所有串 ,j代表起始 位置
 69             {
 70                 temp1=0;
 71                 getcha(i,j,s[te]);//得到需要匹配的串
 72                 getNext(i);
 73                 for(int k=0;k<n;k++)
 74                 {
 75                     if(k!=te)
 76                     {
 77                         temp1=find(s[k],leni[k],i);
 78                         if(temp1==0)
 79                         {
 80                             reverse(s[k],s[k]+leni[k]);
 81                             temp1=find(s[k],leni[k],i);
 82                             if(temp1==0)
 83                             {
 84                                 reverse(s[k],s[k]+leni[k]);
 85                                 break;
 86                             }
 87                             reverse(s[k],s[k]+leni[k]);
 88                             if(temp1==0)
 89                                 break;
 90                         }
 91                     }
 92                 }
 93             if(temp1==1)
 94             {
 95                 temp2=i;
 96                 break;
 97             }
 98         }
 99         if(temp1==1)
100         break;
101     }
102         if(temp2==-1)
103         cout<<"0"<<endl;
104         else
105         cout<<temp2<<endl;
106
107     }
108 } 

时间: 2024-08-03 20:21:17

HDU 1238 (暴力反转KMP)的相关文章

poj 1226 hdu 1238 Substrings 求若干字符串正串及反串的最长公共子串 2002亚洲赛天津预选题

题目:http://poj.org/problem?id=1226 http://acm.hdu.edu.cn/showproblem.php?pid=1238 其实用hash+lcp可能也可以,甚至可能写起来更快,不过我没试,我最近在练习后缀数组,所以来练手 后缀数组的典型用法之一----------------后缀数组+lcp+二分 思路:1.首先将所有的字符串每读取一个,就将其反转,作为一组,假设其下标为i到j,那么cnt[i]到cnt[j]都标记为一个数字(这个数字意思是第几个读入的字符

hdu 2328 Corporate Identity(kmp)

Problem Description Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recentl

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

hdu 5510 Bazinga(字符串kmp)

Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2287    Accepted Submission(s): 713 Problem Description Ladies and gentlemen, please sit up straight.Don't tilt your head. I'm serious.For

hdu 1711 Number Sequence(KMP)

# include <stdio.h> # include <string.h> # include <algorithm> using namespace std; int n,m,next[10010],a[1000010],b[10010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<m) { if(j==-1||b[i]==b[j]) i++,j++,next[i]=j; else j=next[

HDU 1711 Number Sequence KMP题解

KMP查找整数数列,不是查找字符串. 原理是一样的,不过把字符串转换为数列,其他基本上是一样的. #include <stdio.h> #include <string.h> const int MAX_N = 1000001; const int MAX_M = 10001; int strN[MAX_N], strM[MAX_M], next[MAX_M], N, M; void getNext() { memset(next, 0, sizeof(int) * M); for

HDU 1686 Oulipo(KMP)

Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book: Tout avait Pair normal, mais tout s'affirmait faux. Tout avait Fair

HDU 1238

好吧,这题直接搜索就可以了,不过要按照长度最短的来搜,很容易想得到. 记得ACM比赛上有这道题,呃..不过,直接搜..呵呵了,真不敢想. 1 #include <iostream> 2 #include <cstdio> 3 #include <string.h> 4 #include <algorithm> 5 using namespace std; 6 7 char str[105][105]; 8 char s1[105],s2[105]; 9 10

HDU 3374 String Problem (KMP+最大最小表示)

KMP,在有循环节的前提下: 循环节 t = len-next[len], 个数num = len/(len-next[len]); 个人理解,如果有循环节,循环节长度必定小于等于len/2, 换句话说next[len]>=len/2; 对于len%(len-next)!=0的这种情况不讨论,循环节不存在. 下面是假设循环节存在的情况 当次数等于2, 对于abcabc这种情况就不用说了,len = 6, next[len] = 3; 当次数大于2, 对于串a1 a2 a3 a4 a5 a6 a7