HDU5510-Bazinga-kmp或者hash-毒瘤題
阿新 • • 發佈:2019-01-28
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
目錄
題意:傳送門
原題目描述在最下面。
求最大的下標,滿足存在一個且第個串不是第個串的子串。
思路:
列舉,匹配求解。
有一個小優化就是:如果是的子串,是的子串,那麼對於和就不用跑一次匹配演算法。然後順便記錄一下這個串有沒有不能和它匹配的串,有就標記一下,方便求解答案。
最後倒著列舉一遍得出答案。
感覺有點sb的就是最壞情況這個剪枝並沒有用處啊???難道不是嗎,該T還得T
kmp:468ms
#include <cstdio>
#include <cstring>
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
int n, m;
char ar[505][2010];
int len[505],nex[2010];
inline void get_next(char *t,int lent){
nex[0] = -1;
for(int i = 0,k = -1;i < lent;){
if(k==-1||t[i] == t[k]){
++k;++i;
nex[i]=k;
}else k = nex[k];
}
}
inline bool kmp(char *s,int lens,char *t,int lent){
if(lens<lent)return 0;
if(lent==1){
if(s[0]==t[0])return true;
return false;
}
get_next(t,lent);
int i = 0, j = 0;
while(i < lens&&j<lent) {
if(j==-1||s[i] == t[j]){
i++;j++;
if (j==lent){
return 1;
}
}else j=nex[j];
}
return 0;
}
int vis[505][505],mp[505];
int main(){
int tim,tc=0;
scanf("%d",&tim);
while(tim--){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s", ar[i]);
len[i]=strlen(ar[i]);
}
mme(vis,0);mme(mp,0);
int ans=-1;
for(int i=2;i<=n;++i){
for(int j = i-1; j >= 1; --j){
if(len[j]>len[i]){
vis[i][0]=-1;
continue;
}
if(mp[j]){
vis[i][j]=1;
mp[j]=i;
continue;
}
if(kmp(ar[i],len[i],ar[j],len[j])){
vis[i][j]=1;
mp[j]=i;
}else vis[i][0]=-1;
}
if(ans!=-1)break;
}
for(int i=n;i>=1;--i){
if(vis[i][0]==-1){
ans=i;break;
}
}
printf("Case #%d: %d\n", ++tc, ans);
}
return 0;
}
hash 312ms
#pragma comment(linker,"/STACK:102400000,102400000")
#include <bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
const int N = 1e5 + 7;
const int MX = 2e6 + 7;
const uLL base = 131;
int n, m;
int len[505],vis[505][505],mp[505];
char t[2010];
uLL pw[2007], hs[515][2007];
void get_hash(int k, int lent){
hs[k][0] = 0;
for(int i = 1;i <= lent; ++i){
hs[k][i] = hs[k][i-1]*base + (t[i]-'a');
}
}
uLL calc(int k, int l, int r){
return hs[k][r]-hs[k][l-1]*pw[r-l+1];
}
int main(){
pw[0] = 1;
for(int i = 1;i <= 2005; ++i){
pw[i] = pw[i-1]*base;
}
int tim,tc = 0;
scanf("%d", &tim);
while(tim--){
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%s",t+1);
len[i] = strlen(t+1);
get_hash(i, len[i]);
}
mme(vis,0);mme(mp,0);
int ans = -1;
for(int i = 2; i <= n; ++i){
for(int j = i-1; j >= 1; --j){
if(len[j] > len[i]){
vis[i][0]=-1;
continue;
}
if(mp[j])continue;
int flag=0;
for(int h = 1; h+len[j]-1 <= len[i]; ++h){
if(calc(i,h,h+len[j]-1) == hs[j][len[j]]){
flag=1;
break;
}
}
if(flag){
mp[j] = i;
}else{
vis[i][0]=-1;
}
}
}
for(int i=n;i>=1;--i){
if(vis[i][0]==-1){
ans=i;
break;
}
}
printf("Case #%d: %d\n", ++tc, ans);
}
return 0;
}