Skip to content

14132: 【原4132】LCP

题目

题目描述

author: Lmxyy 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4132

Description

在进行完NP-Hard问题研究之后,dhh马上又带着xyy走进了字符串的世界。

dhh首先传授给了xyy一个叫做lcp的东西,所谓lcp即为两个字符串的最长公共前缀。dhh的乒乓球赛奖品除了一张图,还获得了两个字符串,他准备用他们来考考xyy对他所传授的lcp的掌握程度。

xyy:“我肯定全盘掌握了。”

dhh:“那现在我给你这两个字符串,你要立马回答这两个字符串的lcp有多长。”

xyy:“这也太傻了。”

dhh:“那要是我每次还可以修改某个字符串的某个字符呢?”

xyy:“emmmm”

Input Format

第一行两个正整数\(N,M\),表示\(A\)串和\(B\)串的长度。

第二行一个长度为\(N\)的字符串\(A\)。

第三行一个长度为\(M\)的字符串\(B\)。

接下来一个正整数\(Q\),表示dhh的修改个数。

接下来\(Q\)行,每行的形式为\(a \quad b \quad c\)

  • \(a\)的取值为\(0\)或\(1\),\(0\)表示表示修改\(A\)串,\(1\)表示修改\(B\)串;
  • \(b\)表示修改位置,保证合法,下标从\(1\)开始;
  • \(c\)表示修改后的字符。

Output Format

对于每组询问,输出一行一个数,表示答案。

Sample Input 1

6 5
babccb
babcc
4
0 3 a
1 2 c
0 2 c
1 3 a

Sample Output 1

2
1
2
5

Data Range

对于\(40 \%\)的数据,\(N,M \le1000 \),\(Q \le 1000\)。

对于\(100 \%\)的数据,\(N,M \le 100000 \),\(Q \le 200000\)。

字符集大小为所有小写字母。

ligongzzz's solution

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    cin >> n >> m;
    int len = min(n, m);

    vector<int> lcp(len, 0);
    string A, B;
    cin >> A >> B;

    int cur_pos = 0;
    for (; cur_pos < len && A[cur_pos] == B[cur_pos]; ++cur_pos);
    lcp[0] = cur_pos;

    int q;
    cin >> q;

    for (; q > 0; --q) {
        int a, b;
        char c;
        cin >> a >> b;
        cin.get();
        cin >> c;
        if (b > len)
            continue;
        if (a == 0)
            A[b - 1] = c;
        else
            B[b - 1] = c;

        --b;
        for (cur_pos = 0; lcp[cur_pos] <= b; cur_pos = lcp[cur_pos]);
        if (A[b] != B[b]) {

        }
    }

    return 0;
}

WashSwang's solution

#include <iostream>
#include <cstdio>
using namespace std;
int tr[2000000],ans[200001],n,m,q,x,y,step,width,p,tmp;//tr代表节点对应区间的LCP
char a[2][200001],ch;
int main() {
    scanf("%d%d",&n,&m);
    scanf("%s",a[0]);
    scanf("%s",a[1]);
    scanf("%d",&q);
    n=min(n,m);
    for (m=1;m<n;m<<=1);
    for (int i=m;i<m+n;++i)
        if (a[0][i-m]==a[1][i-m]) tr[i]=1;
    width=m>>1;
    step=1;
    for (int i=m-1;i>=1;--i)
    {
        if (i<width){step<<=1;width>>=1;}
        if (tr[i<<1]==step) tr[i]=tr[i<<1]+tr[(i<<1)+1];
        else tr[i]=tr[i<<1];
    }
    for (int i=0;i<q;++i)
    {
        scanf("%d%d",&x,&y);
        getchar();
        scanf("%c",&ch);
        a[x][y-1]=ch;
        if (y<=n){
            if (tr[m+y-1]!=(a[0][y-1]==a[1][y-1])) {
                tr[m+y-1]=(a[0][y-1]==a[1][y-1]);
                step = 1;
                p = m + y - 1;
                while ((p >>= 1) > 0) {
                    tmp=tr[p];
                    if (tr[p << 1] == step) tr[p] = tr[p << 1] + tr[(p << 1)|1];
                    else tr[p] = tr[p << 1];
                    if (tr[p]==tmp) break;//若值未更新则不再上溯
                    step <<= 1;
                }
            }
        }
        ans[i]=tr[1];
    }
    for (int i=0;i<q;++i) printf("%d\n",ans[i]);
    return 0;
}