HDU5510-Bazinga-kmp或者hash-毒瘤题

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

题意:传送门

 原题目描述在最下面。
 求最大的下标 i i ,满足存在一个j(ji)且第 j j 个串不是第i个串的子串。

思路:

O(n2) O ( n 2 ) 枚举, kmporhash k m p o r h a s h 匹配求解。
 有一个小优化就是:如果 k k j的子串, j j i的子串,那么对于 k k i就不用跑一次匹配算法。然后顺便记录一下这个串有没有不能和它匹配的串,有就标记一下,方便求解答案。
 最后倒着枚举一遍得出答案。

感觉有点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;
}


原题目描述:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值