<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      *題解:P14363 [CSP-S 2025] 諧音替換 / replace

      原題鏈接

      解析

      Solution 1

      由題意得,能替換的位置一定是 \(s_1\) 能匹配上 \(t_1\)\(s_2\) 能匹配上 \(t_2\) 的位置。替換是否有效就取決于 \(t_1\) 替換掉的子串左右兩邊的串是否和 \(t_2\) 相同。所以可以處理出 \(t_1\)\(t_2\) 的最長公共前綴 (LCP) 與最長公共后綴 (LCS),利用 KMP 進(jìn)行匹配,根據(jù)匹配到的位置判斷是否計(jì)入答案。具體地,如果匹配到的串能夠覆蓋 \(t_1\)\(t_2\) 不同的區(qū)間,也就是除去 LCP 和 LCS 后剩下的中間部分,則計(jì)入答案,否則說明替換后兩串仍然不同,不計(jì)入答案。

      需要預(yù)處理出 \(s\)\(nxt\) 數(shù)組用于匹配。

      時(shí)間復(fù)雜度 \(O(nL)\),期望得分 25~30。

      Solution 2

      \(s_1,s_2\) 真正起作用的那一段子串,也即 \(s_1,s_2\) 分別除去 LCP 和 LCS 的那一段子串然后拼接而成的串為 \(s'\),稱 \(t_1,t_2\) 經(jīng)過相同處理得到的子串為 \(t'\)。例如,對于 \(s_1=\texttt{xabcx},s_2=\texttt{xadex}\),其 LCP 為 \(\texttt{xa}\),LCS 為 \(\texttt{x}\),中間部分分別為 \(\texttt{bc}\)\(\texttt{de}\),拼起來就是 \(s'=\texttt{bcde}\)

      對于一對 \(t_1,t_2\),我們只需要考慮能夠使得 \(s'=t'\)\(s_1,s_2\),這其實(shí)代表著至多只會有一個(gè)位置能夠匹配。于是,只需要考慮 \(\operatorname{LCP}(s_1,s_2)\) 是否為 \(\operatorname{LCP}(t_1,t_2)\) 的后綴,\(\operatorname{LCS}(s_1,s_2)\) 是否為 \(\operatorname{LCS}(t_1,t_2)\) 的前綴。

      這個(gè)問題可以用哈希解決,具體地,可以將 \(s_1,s_2\) 分成 LCP,\(s'\),LCS 三段進(jìn)行哈希,這樣就可以使用 map 存儲按照 \(s'\) 的分類的 LCP 與 LCS。詢問時(shí),也對 \(t_1,t_2\) 進(jìn)行三段式哈希,注意需要對 LCP 的每個(gè)后綴,LCS 的每個(gè)前綴進(jìn)行哈希并分別存入一個(gè) map 里。

      時(shí)間復(fù)雜度 \(O(nq \log L)\),期望得分 50。

      Solution 3

      我們發(fā)現(xiàn),左右兩部分的匹配其實(shí)是一個(gè)匹配前綴的過程(左邊那部分倒過來就從后綴變成前綴了),所以考慮能否使用字典樹來解決。

      首先我們要開兩棵樹,分別存儲所有 \(s_1,s_2\) 的 LCP 的反轉(zhuǎn)和 LCS,記它們?yōu)?\(LT\)\(RT\)

      \(\operatorname{LCP}(t_1,t_2)\) 的反轉(zhuǎn)在 \(LT\) 上最終到達(dá)的結(jié)點(diǎn)為 \(lx\)\(\operatorname{LCS}(t_1,t_2)\)\(RT\) 上最終到達(dá)的結(jié)點(diǎn)為 \(rx\)\(\operatorname{LCP}(s_1,s_2)\) 的反轉(zhuǎn)在 \(LT\) 上最終到達(dá)的結(jié)點(diǎn)為 \(ly\)\(\operatorname{LCS}(s_1,s_2)\)\(RT\) 上最終到達(dá)的結(jié)點(diǎn)為 \(ry\)。那么,\(s_1,s_2\) 可以對 \(t_1,t_2\) 作貢獻(xiàn)當(dāng)且僅當(dāng) \(ly\)\(lx\) 的祖先且 \(ry\)\(rx\) 的祖先。也就是說,我們希望統(tǒng)計(jì)有多少個(gè) \(lx\) 的祖先 \(ly\) 對應(yīng)的 \(ry\)\(rx\) 的祖先。于是,我們可以將詢問離線下來在樹上進(jìn)行標(biāo)記,在 \(lx\) 處標(biāo)記 \(rx\) 的值,對 \(LT\) 進(jìn)行 dfs,對于 dfs 過程中遇到的每個(gè) \(ly\),對 \(RT\) 上與其對應(yīng)的 \(rx\) 的子樹中的點(diǎn)全體加 \(1\),回溯時(shí)消除影響。對于遇到的每個(gè) \(lx\),查詢 \(RT\)\(rx\) 的值。查詢和修改的過程可以用樹狀數(shù)組實(shí)現(xiàn),具體地,先將 \(RT\) 按照 dfs 序編號,記為 \(dfn\),并處理出每個(gè)點(diǎn)的子樹大小 \(siz\),然后按照 dfs 序建立樹狀數(shù)組,這樣,子樹修改就變?yōu)樵?\([dfn_x,dfn_x+siz_x)\) 的范圍內(nèi)進(jìn)行修改。

      時(shí)間復(fù)雜度 \(O((n+q)\log L)\),期望得分 100。

      代碼

      小心 \(s_1=s_2\)\(|t_1|\not=|t_2|\) 的情況。

      #include <bits/stdc++.h>
      using namespace std;
      typedef long long ll;
      typedef pair<int,int> pii;
      const int N = 5.2e6 + 5,M = 2e5 + 5;
      struct Trie{
      	int pos[N][26],cnt = 1;
      }tl,tr,trm;
      int vm[N],mcnt,rootl[M],rootr[M];
      vector<int> pos[N];
      vector<pii> query[N];
      int res[M];
      string s1[M],s2[M],t1[M],t2[M];
      int dfnl[N],dfnr[N],rcnt,siz[N];
      int b[N];
      void dfsr(int x){
      	dfnr[x] = ++rcnt;
      	siz[x] = 1;
      	for(int i=0;i<26;i++){
      		if(tr.pos[x][i]) dfsr(tr.pos[x][i]),siz[x] += siz[tr.pos[x][i]];
      	}
      	
      }
      void add(int x,int k){
      	for(;x < N;x += x & -x){
      		b[x] += k;
      	}
      }
      int ask(int x){
      	int res = 0;
      	for(;x;x -= x & -x){
      		res += b[x];
      	}
      	return res;
      }
      void dfsl(int x){
      	for(int i : pos[x]){
      		add(dfnr[i],1);
      		add(dfnr[i] + siz[i],-1);
      	}
      	for(int i=0;i<query[x].size();i++){
      		pii p = query[x][i];
      		res[p.second] = ask(dfnr[p.first]);
      	}
      	for(int i=0;i<26;i++){
      		if(tl.pos[x][i]){
      			dfsl(tl.pos[x][i]);
      		}
      	}
      	for(int i : pos[x]){
      		add(dfnr[i],-1);
      		add(dfnr[i] + siz[i],1);
      	}
      }
      int main(){
      	ios::sync_with_stdio(false);
      	cin.tie(0);
      	int n,q;
      	cin>>n>>q;
      	for(int i=1;i<=n;i++){
      		cin>>s1[i]>>s2[i];
      		if(s1[i] == s2[i]) continue;
      		int m = (int)s1[i].size() - 1;
      		int l = 0,r = m;
      		while(s1[i][l] == s2[i][l]) l++;
      		while(s1[i][r] == s2[i][r]) r--; 
      		string s = s1[i].substr(l,r - l + 1) + s2[i].substr(l,r - l + 1);
      		int mpos,rpos;
      		int p = 1;
      		for(int j=0;j<s.size();j++){
      			if(!trm.pos[p][s[j] - 'a']) trm.pos[p][s[j] - 'a'] = ++trm.cnt;
      			p = trm.pos[p][s[j] - 'a'];  
      		}
      		if(!vm[p]){
      			vm[p] = ++mcnt;
      			rootl[vm[p]] = ++tl.cnt;
      			rootr[vm[p]] = ++tr.cnt;
      		}
      		mpos = vm[p];
      		p = rootr[mpos];
      		for(int j=r + 1;j<=m;j++){
      			if(!tr.pos[p][s1[i][j] - 'a']) tr.pos[p][s1[i][j] - 'a'] = ++tr.cnt;
      			p = tr.pos[p][s1[i][j] - 'a']; 
      		}
      		rpos = p;
      		p = rootl[mpos];
      		for(int j=l - 1;j>=0;j--){
      			if(!tl.pos[p][s1[i][j] - 'a']) tl.pos[p][s1[i][j] - 'a'] = ++tl.cnt;
      			p = tl.pos[p][s1[i][j] - 'a']; 
      		}
      		pos[p].push_back(rpos);
      	}
      	for(int i=1;i<=mcnt;i++){
      		dfsr(rootr[i]);
      	}
      	for(int i=1;i<=q;i++){
      		cin>>t1[i]>>t2[i];
      		if(t1[i].size() != t2[i].size()) continue;
      		int m = t1[i].size() - 1;
      		int l = 0,r = m;
      		while(t1[i][l] == t2[i][l]) l++;
      		while(t1[i][r] == t2[i][r]) r--; 
      		string t = t1[i].substr(l,r - l + 1) + t2[i].substr(l,r - l + 1);
      		int p = 1;
      		bool flag = true;
      		int mpos,rpos;
      		for(int j=0;j<t.size();j++){
      			if(!trm.pos[p][t[j] - 'a']){
      				flag = false;
      				break;
      			}
      			p = trm.pos[p][t[j] - 'a'];
      		}
      		if(!flag) continue;
      		mpos = vm[p];
      		p = rootr[mpos];
      		for(int j=r + 1;j<=m;j++){
      			if(!tr.pos[p][t1[i][j] - 'a']){
      				break;
      			}
      			p = tr.pos[p][t1[i][j] - 'a'];
      		}
      		rpos = p;
      		p = rootl[mpos];
      		for(int j=l - 1;j>=0;j--){
      			if(!tl.pos[p][t1[i][j] - 'a']){
      				break;
      			}
      			p = tl.pos[p][t1[i][j] - 'a'];
      		}
      		query[p].push_back({rpos,i});
      	}
      	for(int i=1;i<=mcnt;i++){
      		dfsl(rootl[i]);
      	}
      	for(int i=1;i<=q;i++){
      		cout<<res[i]<<"\n";
      	}
      	return 0;
      }
      
      posted @ 2025-11-05 17:12  yuyce  閱讀(8)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 伊人色综合久久天天小片| 亚洲精品久久国产高清| 中文字幕成熟丰满人妻| 国产偷国产偷亚洲清高网站| 亚洲熟妇无码av另类vr影视| 亚洲精品一品二品av| 亚洲69视频| www亚洲精品| 日本国产精品第一页久久| 亚洲一区精品伊人久久| 97se亚洲国产综合在线| 国产特级毛片aaaaaa毛片| 成人无码区在线观看| 国产av综合一区二区三区| 国产亚洲av夜间福利香蕉149| 久久中文字幕日韩无码视频| 久久国内精品一国内精品| 中文字幕久久精品波多野结| 国产办公室秘书无码精品99| 亚成区成线在人线免费99| 一出一进一爽一粗一大视频| 国产91小视频在线观看| 九九热在线视频免费观看| 国产性色av免费观看| 国产熟女一区二区三区四区| 国产对白老熟女正在播放| 亚洲日本乱码在线观看| 中文字幕亚洲男人的天堂| 潮喷失禁大喷水无码| 宜昌市| 欧美激情内射喷水高潮| 午夜性色一区二区三区不卡视频| 社会| 亚洲中文字幕一区二区| 欧美特级午夜一区二区三区| 免费观看欧美猛交视频黑人| 亚洲天堂亚洲天堂亚洲天堂| 久久99热只有频精品8| 18禁裸乳无遮挡啪啪无码免费| 柳河县| 久久99精品国产麻豆婷婷|