BNU 34990(字符串题目)

题意:
给定两个串(串长都小于1e5) , 从第一个串0位置开始如果该位置开始与第二个串“匹配”(至多两个位置字母不同) , 记为一个可行点, 那么求最小可行点。

分析:
直接枚举位置,我们发现当前被枚举的点,有一个确定性因素,即把该点当做了起始匹配位置(这一点非常重要),那么最长会有多长哪,贪心的想法想一下,即可。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long llu;
#define clr(a , x) memset(a , x, sizeof(a));
#define rep(i , n) for(int i=0; i<(int)n ; i++)
#define rep1(i , x, y) for(int i=(int)x;i<=(int)y;i++)
#define repd(i , y ,x) for(int i=(int)y;i>=(int)x;i--)

const int N = 1e5 + 100;
const llu base = 123;
llu ha1[N] , ha2[N] ,POW[N];
char s1[N],s2[N];
llu get(llu* s , int i,int len){
    return s[i] - s[i+len]*POW[len];
}
int n,m;
llu cal(int i, int j){
   int x = 0 , y = min(m - j , n - i) + 1;
   while(x < y){
      int mid = (x + y)>>1;
      if(get(ha1 , i , mid) == get(ha2 , j ,mid)) x = mid + 1;
      else y = mid;
   }
   return x-1;
}
void init(){
    scanf("%s %s",s1 , s2);
    n = strlen(s1) , m = strlen(s2);
    ha1[n] = 0;
    repd(i , n-1 , 0) ha1[i] = ha1[i+1]*base + s1[i] - 'a';
    ha2[m] = 0;
    repd(i , m-1 , 0) ha2[i] = ha2[i+1]*base + s2[i] - 'a';
}
int solve(){
    if(n < m) return -1;
    rep(i ,n - m + 1){
        int cnt = 0 , num = 0 , x = i , y = 0;
        rep(j , 3){
             int td = cal(x , y);
             x+=td; y+=td;
             if(j < 2) ++x , ++y;
             if(y >= m){
                  return i;
             }
        }
    }
    return -1;
}
int main()
{
   POW[0] = 1;
   rep1(i , 1 , N-1) POW[i] = POW[i-1]*base;
   int T , kase = 1;
   scanf("%d",&T);
   while(T--){
        init();
        printf("Case #%d: %d\n",kase++,solve());
   }
   return 0;
}




你可能感兴趣的:(BNU 34990(字符串题目))