[CSP-S 2025] 谐音替换题解

P14363 [CSP-S 2025] 谐音替换 / replace(民间数据)

题目背景

由于评测机性能差异,本题时限提升 1 秒。

测试数据未经过检验,可能存在问题,或者可能存在错误做法获得较高分数,仅供参考。

  • 2025.11.02 10:53 民间数据更新:增加了少量 ∣t1∣≠∣t2∣|t_1| \neq |t_2|t1=t2 的测试点。
  • 2025.11.02 10:59 民间数据更新:降低了直接输出 000 的得分。

题目描述

小 W 是一名喜欢语言学的算法竞赛选手。在语言学中,谐音替换是指将原有的字词替换为读音相同或相近的字词。小 W 发现,谐音替换的过程可以用字符串来进行描述。具体地,小 W 将谐音替换定义为以下字符串问题:

给定 nnn 个字符串二元组,第 iii (1≤i≤n1 \leq i \leq n1in) 个字符串二元组为 (si,1,si,2)(s_{i,1}, s_{i,2})(si,1,si,2),满足 ∣si,1∣=∣si,2∣|s_{i,1}| = |s_{i,2}|si,1=si,2,其中 ∣s∣|s|s 表示字符串 sss 的长度。

对于字符串 sss,定义 sss替换如下:

  • 对于 sss 的某个子串 yyy,若存在 1≤i≤n1 \leq i \leq n1in 满足 y=si,1y = s_{i,1}y=si,1,则将 yyy 替换为 y′=si,2y' = s_{i,2}y=si,2。具体地,设 s=x+y+zs = x + y + zs=x+y+z,其中 xxxzzz 可以为空,“+” 表示字符串拼接,则 sss 的替换将得到字符串 s′=x+y′+zs' = x + y' + zs=x+y+z

小 W 提出了 qqq 个问题,第 jjj (1≤j≤q1 \leq j \leq q1jq) 个问题会给定两个不同的字符串 tj,1,tj,2t_{j,1}, t_{j,2}tj,1,tj,2,她想知道有多少种字符串 tj,1t_{j,1}tj,1 的替换能够得到字符串 tj,2t_{j,2}tj,2。两种 sss 的替换不同当且仅当子串 yyy 的位置不同或用于替换的二元组 (si,1,si,2)(s_{i,1}, s_{i,2})(si,1,si,2) 不同,即 x,zx, zx,z 不同或 iii 不同。你需要回答小 W 提出的所有问题。

输入格式

输入的第一行包含两个正整数 n,qn, qn,q,分别表示字符串二元组的数量和小 W 提出的问题的数量。

输入的第 i+1i+1i+1 (1≤i≤n1 \leq i \leq n1in) 行包含两个字符串 si,1,si,2s_{i,1}, s_{i,2}si,1,si,2,表示第 iii 个字符串二元组。

输入的第 j+n+1j+n+1j+n+1 (1≤j≤q1 \leq j \leq q1jq) 行包含两个字符串 tj,1,tj,2t_{j,1}, t_{j,2}tj,1,tj,2,表示小 W 提出的第 jjj 个问题。

输出格式

输出 qqq 行,其中第 jjj (1≤j≤q1 \leq j \leq q1jq) 行包含一个非负整数,表示替换后得到字符串 tj,2t_{j,2}tj,2 的字符串 tj,1t_{j,1}tj,1 的替换的数量。

输入输出样例 #1

输入 #1

4 2
xabcx xadex
ab cd
bc de
aa bb
xabcx xadex
aaaa bbbb

输出 #1

2
0

输入输出样例 #2

输入 #2

3 4
a b
b c
c d
aa bb
aa b
a c
b a

输出 #2

0
0
0
0

说明/提示

【样例 1 解释】

对于小 W 的第一个询问,共有 222t1,1t_{1,1}t1,1 的替换能够得到 t1,2t_{1,2}t1,2:

  1. x,zx, zx,z 均为空串,y=xabcxy = \text{xabcx}y=xabcx, i=1i = 1i=1,则 y′=xadexy' = \texttt{xadex}y=xadex,替换后得到 xadex\text{xadex}xadex
  2. x=xax = \texttt{xa}x=xa, y=bcy = \texttt{bc}y=bc, z=xz = \texttt{x}z=x, i=3i = 3i=3,则 y′=dey' = \texttt{de}y=de,替换后得到 xadex\texttt{xadex}xadex

【样例 3】

见选手目录下的 replace/replace3.inreplace/replace3.inreplace/replace3.inreplace/replace3.ansreplace/replace3.ansreplace/replace3.ans

该样例满足测试点 11, 12 的约束条件。

【样例 4】

见选手目录下的 replace/replace4.inreplace/replace4.inreplace/replace4.inreplace/replace4.ansreplace/replace4.ansreplace/replace4.ans

该样例满足测试点 15, 16 的约束条件。

【数据范围】

L1=∑i=1n∣si,1∣+∣si,2∣L_1 = \sum_{i=1}^{n} |s_{i,1}| + |s_{i,2}|L1=i=1nsi,1+si,2, L2=∑j=1q∣tj,1∣+∣tj,2∣L_2 = \sum_{j=1}^{q} |t_{j,1}| + |t_{j,2}|L2=j=1qtj,1+tj,2。对于所有测试数据,保证:

  • 1≤n,q≤2×1051 \leq n, q \leq 2 \times 10^51n,q2×105;
  • 2≤L1,L2≤5×1062 \leq L_1, L_2 \leq 5 \times 10^62L1,L25×106;
  • 对于所有 1≤i≤n1 \leq i \leq n1in, si,1,si,2s_{i,1}, s_{i,2}si,1,si,2 均仅包含小写英文字母,且 ∣si,1∣=∣si,2∣|s_{i,1}| = |s_{i,2}|si,1=si,2;
  • 对于所有 1≤j≤q1 \leq j \leq q1jq, tj,1,tj,2t_{j,1}, t_{j,2}tj,1,tj,2 均仅包含小写英文字母,且 tj,1≠tj,2t_{j,1} \neq t_{j,2}tj,1=tj,2

::cute-table{tuack}

测试点编号n,q≤n, q \leqn,qL1,L2≤L_1, L_2 \leqL1,L2特殊性质
1,21, 21,210210^2102200200200
3∼53 \sim 53510310^31032 0002\,0002000^
666^10610^6106AB
7,87, 87,810410^4104^A
9,109, 109,102×1052 \times 10^52×105^B
11,1211, 1211,12^2×1062 \times 10^62×106
13,1413, 1413,14^5×1065 \times 10^65×106A
15,1615, 1615,16^^B
17∼2017 \sim 201720^^

特殊性质 A:q=1q = 1q=1

特殊性质 B:定义字符串 sss特别的,当且仅当字符串 sss 仅包含字符 aaabbb,且字符 bbbsss 中出现恰好一次。对于所有 1≤i≤n1 \leq i \leq n1in, si,1,si,2s_{i,1}, s_{i,2}si,1,si,2 均为特别的,且对于所有 1≤j≤q1 \leq j \leq q1jq, tj,1,tj,2t_{j,1}, t_{j,2}tj,1,tj,2 均为特别的。

思路

首先,暴力显然不可,所以,我们可以先提取每个输入的前后缀不同开始之处的区间,然后用vector存不同,map存储vector编号,然后直接对比,提取t串的前后缀不同开始之处的区间,进行前后缀对比。

暴力代码

#include<bits/stdc++.h>
using namespace std;
int n,q,sd=0,op=0,qp=0,hp=0,os=0,oi=0,bk=0,ioi=0;
struct one{
    string s1,s2,s3,s4;
    int q,h;
}a[200005];
struct two{
    string s1,s2;
};
vector<two> v[200005];
map<string,int> mp;
string t1,t2,tt1,tt2;
int main(){
	cin>>n>>q;
    sd=0;
    bk=0;
    for(int i=1;i<=n;i++){
        cin>>a[i].s1>>a[i].s2;
        a[i].q=a[i].h=0;
        ioi=0;
        for(int j=0;j<a[i].s1.size();j++){
            if(a[i].s1[j]==a[i].s2[j]){
                a[i].q++;
            }
            else{
                break;
            }
        }
        for(int j=a[i].s1.size()-1;j>=0;j--){
            if(a[i].s1[j]==a[i].s2[j]){
                a[i].h++;
            }
            else{
                break;
            }
        }
        a[i].s3=a[i].s4="";
        for(int j=a[i].q;j<a[i].s1.size()-a[i].h;j++){
            a[i].s3+=a[i].s1[j];
            a[i].s4+=a[i].s2[j];
        } 
        t1=t2="";
        for(int j=a[i].q-1;j>=0;j--){
            t1+=a[i].s1[j];
        }
        for(int j=a[i].s1.size()-a[i].h;j<a[i].s1.size();j++){
            t2+=a[i].s1[j];
        }
        if(bk==0) for(int j=0;j<a[i].s1.size();j++){
            if((a[i].s1[j]!='a'&&a[i].s1[j]!='b')||(a[i].s2[j]!='a'&&a[i].s2[j]!='b')){
                ioi=1;
                break;
            }
        }
        if(ioi==1){
            bk=1;
        }
        //cout<<a[i].s3<<" "<<a[i].s4<<" "<<a[i].q<<" "<<a[i].h<<endl;
        if(mp[(string)(a[i].s3+">"+a[i].s4)]==0){
            mp[(string)(a[i].s3+">"+a[i].s4)]=++sd;
            v[sd].push_back({t1,t2});
        }
        else{
            v[mp[(string)(a[i].s3+">"+a[i].s4)]].push_back({t1,t2});
        }
    }
    for(int i=1;i<=q;i++){
        cin>>t1>>t2;
        if(t1.size()!=t2.size()){
            cout<<0<<endl;
        }
        else{
            op=0;
            qp=hp=0;
            for(int j=0;j<t1.size();j++){
                if(t1[j]==t2[j]){
                    qp++;
                }
                else{
                    break;
                }
            }
            for(int j=t1.size()-1;j>=0;j--){
                if(t1[j]==t2[j]){
                    hp++;
                }
                else{
                    break;
                }
            }
            tt1=tt2="";
            for(int j=qp;j<t1.size()-hp;j++){
                tt1+=t1[j];
                tt2+=t2[j];
            }
            os=mp[(string)(tt1+">"+tt2)];
            //cout<<os<<endl;
            if(bk!=0){
                for(int j=0;j<v[os].size();j++){
                	//cout<<v[os][j].s1.size()<<" "<<qp<<" "<<v[os][j].s2.size()<<" "<<hp<<endl;
                    if(v[os][j].s1.size()<=qp&&v[os][j].s2.size()<=hp){
                        oi=0;
                        for(int o=0;o<v[os][j].s1.size();o++){
                            if(v[os][j].s1[o]!=t1[qp-o-1]){
                                oi=1;
                                break;
                            }
                        }
                        //cout<<oi<<endl;
                        if(oi==0){
                            for(int o=0;o<v[os][j].s2.size();o++){
                                if(v[os][j].s2[o]!=t1[t1.size()-hp+o]){
                                    oi=1;
                                    break;
                                }
                            }                            
                        }
                        if(oi==0){
                            op++;
                        }
                    }
                }
                cout<<op<<endl;
            }
            else{
                for(int j=0;j<v[os].size();j++){
                	//cout<<v[os][j].s1.size()<<" "<<qp<<" "<<v[os][j].s2.size()<<" "<<hp<<endl;
                    if(v[os][j].s1.size()<=qp&&v[os][j].s2.size()<=hp){
                        op++;
                    }
                }
                cout<<op<<endl;
            }
        }
    }
	return 0;
}

发现过不了,考虑优化,用map求有没有找过,找过直接输出即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
int n,q,sd=0,op=0,qp=0,hp=0,os=0,oi=0,bk=0,ioi=0;
struct one{
    string s1,s2,s3,s4;
    int q,h;
}a[200005];
struct two{
    string s1,s2;
};
vector<two> v[200005];
map<string,int> mp;
map<string,int> mp2;
string t1,t2,tt1,tt2;
int main(){
	cin>>n>>q;
    sd=0;
    bk=0;
    for(int i=1;i<=n;i++){
        cin>>a[i].s1>>a[i].s2;
        a[i].q=a[i].h=0;
        ioi=0;
        for(int j=0;j<a[i].s1.size();j++){
            if(a[i].s1[j]==a[i].s2[j]){
                a[i].q++;
            }
            else{
                break;
            }
        }
        for(int j=a[i].s1.size()-1;j>=0;j--){
            if(a[i].s1[j]==a[i].s2[j]){
                a[i].h++;
            }
            else{
                break;
            }
        }
        a[i].s3=a[i].s4="";
        for(int j=a[i].q;j<a[i].s1.size()-a[i].h;j++){
            a[i].s3+=a[i].s1[j];
            a[i].s4+=a[i].s2[j];
        } 
        t1=t2="";
        for(int j=a[i].q-1;j>=0;j--){
            t1+=a[i].s1[j];
        }
        for(int j=a[i].s1.size()-a[i].h;j<a[i].s1.size();j++){
            t2+=a[i].s1[j];
        }
        if(bk==0) for(int j=0;j<a[i].s1.size();j++){
            if((a[i].s1[j]!='a'&&a[i].s1[j]!='b')||(a[i].s2[j]!='a'&&a[i].s2[j]!='b')){
                ioi=1;
                break;
            }
        }
        if(ioi==1){
            bk=1;
        }
        //cout<<a[i].s3<<" "<<a[i].s4<<" "<<a[i].q<<" "<<a[i].h<<endl;
        if(mp[(string)(a[i].s3+">"+a[i].s4)]==0){
            mp[(string)(a[i].s3+">"+a[i].s4)]=++sd;
            v[sd].push_back({t1,t2});
        }
        else{
            v[mp[(string)(a[i].s3+">"+a[i].s4)]].push_back({t1,t2});
        }
    }
    for(int i=1;i<=q;i++){
        cin>>t1>>t2;
        if(t1.size()!=t2.size()){
            cout<<0<<endl;
        }
        else{
            op=0;
            qp=hp=0;
            for(int j=0;j<t1.size();j++){
                if(t1[j]==t2[j]){
                    qp++;
                }
                else{
                    break;
                }
            }
            for(int j=t1.size()-1;j>=0;j--){
                if(t1[j]==t2[j]){
                    hp++;
                }
                else{
                    break;
                }
            }
            tt1=tt2="";
            for(int j=qp;j<t1.size()-hp;j++){
                tt1+=t1[j];
                tt2+=t2[j];
            }
            os=mp[(string)(tt1+">"+tt2)];
            //cout<<os<<endl;
            if(bk!=0){
                if(mp2[(string)(t1+">"+t2)]!=0){
                    cout<<mp2[(string)(t1+">"+t2)]<<endl; 
                }
                else{
                    for(int j=0;j<v[os].size();j++){
                    	//cout<<v[os][j].s1.size()<<" "<<qp<<" "<<v[os][j].s2.size()<<" "<<hp<<endl;
                        if(v[os][j].s1.size()<=qp&&v[os][j].s2.size()<=hp){
                            oi=0;
                            for(int o=0;o<v[os][j].s1.size();o++){
                                if(v[os][j].s1[o]!=t1[qp-o-1]){
                                    oi=1;
                                    break;
                                }
                            }
                            //cout<<oi<<endl;
                            if(oi==0){
                                for(int o=0;o<v[os][j].s2.size();o++){
                                    if(v[os][j].s2[o]!=t1[t1.size()-hp+o]){
                                        oi=1;
                                        break;
                                    }
                                }                            
                            }
                            if(oi==0){
                                op++;
                            }
                        }
                    }
                    mp2[(string)(t1+">"+t2)]=op;
                    cout<<op<<endl;                    
                }
            }
            else{
                if(mp2[(string)(t1+">"+t2)]!=0){
                    cout<<mp2[(string)(t1+">"+t2)]<<endl; 
                }
                else{
                    for(int j=0;j<v[os].size();j++){
                    	//cout<<v[os][j].s1.size()<<" "<<qp<<" "<<v[os][j].s2.size()<<" "<<hp<<endl;
                        if(v[os][j].s1.size()<=qp&&v[os][j].s2.size()<=hp){
                            op++;
                        }
                    }
                    mp2[(string)(t1+">"+t2)]=op;
                    cout<<op<<endl;                    
                }

            }
        }
    }
	return 0;
}
posted @ 2025-11-03 21:23  bz02_2023f2  阅读(18)  评论(0)    收藏  举报  来源