日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【训练题55:尺取 + 高阶等差】Another String | HDU7015 | 杭电多校五 04题

發布時間:2023/12/10 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【训练题55:尺取 + 高阶等差】Another String | HDU7015 | 杭电多校五 04题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意

  • Another String | HDU7015 | 杭電多校五 04題
    我們說兩個序列 a,ba,ba,bkkk 匹配的,當且僅當 ∣a∣=∣b∣|a|=|b|a=b
    ∑i[ai≠bi]≤k\sum_{i} [a_i\ne b_i]\le ki?[ai??=bi?]k ,即最多有 kkk 個位置不同
    給定一個字符串 SSSkkk
    你需要求出 ?i∈[1,∣S∣?1]\forall i\in[1,|S|-1]?i[1,S?1],串 S[1,i]S[1,i]S[1,i] 的一個子串 aaa 與 串 S[i+1,∣S∣]S[i+1,|S|]S[i+1,S] 的一個子串 bbbkkk 匹配的,問有多少種方案
  • 2≤∣S∣≤30002\le |S|\le 30002S3000
    0≤k≤30000\le k\le 30000k3000

思路

  • 感覺字符串匹配,可能就是字符串或者卷積的題 (???) 就不敢去看
    但是其實這題的做法比較偏想法
  • 首先我們很難按照 i=1~∣S∣?1i=1\sim |S|-1i=1S?1 去分類討論做
    不妨設目前我們有兩個子串 [L1,R1][L1,R1][L1,R1][L2,R2][L2,R2][L2,R2]kkk 匹配的
    那么我們能擴展或收縮到那些其他的子串,保證一定合法的呢?
  • 容易想到,如果 L1,R1L1,R1L1,R1 向右移動一段距離,然后所有合法的子串中,會有許多重復
    那么我們就固定左端點,計算此時有多少合法的右端點
  • 然后去考慮,每一個合法的子串對那些 iii 有貢獻
  • 對于第一個區間 [L1,R1][L1,R1][L1,R1],我們對 i=L1~L2?1i=L1\sim L2-1i=L1L2?1 都有 111 的貢獻
    對于第 xxx 個區間 [L1+x?1,R1][L1+x-1,R1][L1+x?1,R1],我們對 i=L1+x?1~L2?1i=L1+x-1\sim L2-1i=L1+x?1L2?1 都有 111 的貢獻
  • 考慮怎么去快速累加貢獻
    如果只是對一段區間 [x,y][x,y][x,y] 全部有 +1+1+1 的貢獻,我們可以用線段樹,也可以用差分數組 de[x]+1,de[y+1]?1de[x]+1,de[y+1]-1de[x]+1,de[y+1]?1 去做
    但是我們會有 xxx 個區間去做,容易想到去用二階等差de2[L1]+1,de2[R1+1]?1de2[L1]+1,de2[R1+1]-1de2[L1]+1,de2[R1+1]?1
    然后我們讓一階等差 de[L2]?(R1?L1+1)de[L2]-(R1-L1+1)de[L2]?(R1?L1+1) ,這樣就可以達到我們的要求
  • 然后就是,對于所有的左端點 L1L1L1,我們需要找到最大的 R1R1R1 和另一個 L2L2L2,滿足上述區間有 kkk 個不同的位置,或者擴到不能擴為止
    容易想到這是一個尺取,也就是我們的 [L1,R1][L1,R1][L1,R1] 可以在 O(∣S∣)O(|S|)O(S) 內枚舉完
    那么久剩下 L2L2L2 沒有枚舉了,我們令 L2=L1+xL2=L1+xL2=L1+x ,枚舉這個 xxx ,即可枚舉到所有的情況

代碼

  • 時間復雜度:O(∣S∣2)O(|S|^2)O(S2)
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); using namespace std; typedef long long ll; void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x << " ] , ";show(args...);}const int MAX = 3e3+50; const int MOD = 1e9+7; const int INF = 0x3f3f3f3f; const ll LINF = 0x3f3f3f3f3f3f3f3f; const double EPS = 1e-5;char ss[MAX]; int de1[MAX],de2[MAX]; int main() {int T;scanf("%d",&T);while(T--){int n,k;scanf("%d%d",&n,&k);scanf("%s",ss+1);for(int i = 0;i <= n+1;++i)de1[i] = de2[i] = 0;for(int cha = 1;cha <= n-1;++cha){int L1 = 1,L2 = L1 + cha;int R1 = L1-1,R2 = L2-1;int now = 0;while(L2 <= n){while(R1+1 <= L2-1 && R2+1 <= n){if(ss[R1+1] == ss[R2+1])R1++,R2++;else if(now < k)now++,R1++,R2++;else break;}if(L1 <= R1 && now <= k){int len = R1 - L1 + 1;de2[L1]++;de2[R1+1]--;de1[L2]-=len;if(ss[L1] != ss[L2])now--;L1++;L2++;}else{L1++;L2++;R1 = L1;R2 = L2;if(ss[L1] == ss[L2])now = 0;else now = 1;}}}ll tmp = 0,ans = 0;for(int i = 1;i <= n;++i)tmp += de2[i],de1[i] += tmp;tmp = 0;for(int i = 1;i < n;++i)ans += de1[i],printf("%lld\n",ans);}return 0; }

總結

以上是生活随笔為你收集整理的【训练题55:尺取 + 高阶等差】Another String | HDU7015 | 杭电多校五 04题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。