• bzoj2084 hash||manacher


    题意:给一个01串,现在定义一个新的回文方式为0和1相等,而00,11不等。求有多少子串满足这种新的回文方式。
    思路:求多少子串其实就是求每个点最大回文串半径。
    manacher很好写O(n)
    hash的话,我们计算两个哈希值,一个s的一个翻转s后01再反转的哈希值。
    之后二分判断即可。

    manacher:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    const int maxn = 5e5+5;
    
    char ma[maxn<<1];
    int mp[maxn<<1];
    
    void manacher(string s,int len){ 
        int p = 0,r = 0,mid = 0;
        ma[p++] = '$',ma[p++] = '#';
        forn(i,len) ma[p++] = s[i],ma[p++] = '#';
        forn(i,p){
            mp[i] = r>i?min(mp[(mid<<1)-i],r-i):1;
            if(ma[i]=='#')while(1){
                if(ma[i+mp[i]]=='0'&&ma[i-mp[i]]=='1') mp[i]++;
                else if(ma[i+mp[i]]=='1'&&ma[i-mp[i]]=='0') mp[i]++;
                else if(ma[i+mp[i]]=='#') mp[i]++;
                else break;
            }
            if(i+mp[i]>r) r = mp[i]+i,mid = i;
        }
    }
    
    int main(){ 
        IO; 
        int n;cin>>n;
        string s;cin>>s;
        int len = s.size();
        manacher(s,len);
        int ans = 0;
        //forn(i,(len+1)<<1) cerr<<ma[i];
        //cerr<<'
    ';
        forn(i,(len+1)<<1){
          //  cerr<<i<<' '<<mp[i]<<'
    ';
            ans+=mp[i]/2;
        }
        cout << ans<<'
    ';
        return 0;
    }
    

    hash:

    #include <bits/stdc++.h>
    using namespace std;
    #define ull unsigned long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    const int maxn = 5e5+5;
    const int seed = 13331;
    ull S[maxn<<1],S2[maxn<<1],P[maxn<<1];
    int n,len;string s;
    
    void getss(){
        int len = s.size();
        string t = "";t+='#';
        forn(i,len) t+=s[i],t+='#';
        s = t;
    }
    
    bool check(int l,int p){
        ull x,y;
        int p2 = len-p+1;
        x = S[p]-S[p-l]*P[l];
        y = S2[p2]-S2[p2-l]*P[l];
        return x==y;
    }
    
    int main(){
        IO;
        P[0] = 1;
        for1(i,(maxn<<1)-1) P[i] = P[i-1]*seed;
        cin>>n;cin>>s;
        getss();
        len = (n<<1)+1;
        //cerr<<s<<'
    ';
        for1(i,len) S[i] = S[i-1]*seed+s[i-1];
        reverse(s.begin(),s.end());
        forn(i,len) {
            if(s[i]=='0') s[i] = '1';
            else if(s[i]=='1') s[i] = '0';
        }
        for1(i,len) S2[i] = S2[i-1]*seed+s[i-1];
        long long ans = 0;
        //cerr<<s<<'
    ';
        for(int i = 2;i<len;i++){
            int l = 1,r = min(i+1,len-i),res = 1;
            while(l<=r){
                int mid = l+r>>1;
                if(check(mid,i)){
                    l = mid+1;
                    res = mid;
                }else r = mid-1;
            }
            //cerr<<s[i-1]<<' '<<res<<'
    ';
            ans += res/2;
        }
        cout << ans <<'
    ';
        return 0;
    }
    
    人一我百,人十我万。
  • 相关阅读:
    C++函数模板的显示调用与隐式调用
    git显示颜色配置
    STL容器元素应满足的条件
    vector缩减容量
    PAT (Basic Level) Practise:1036. 跟奥巴马一起编程
    Core Java Volume I — 4.10. Class Design Hints
    Core Java Volume I — 4.7. Packages
    蓝牙(Profile)构成
    Android开发之Java必备基础
    主机控制器接口(HCI)
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520307.html
Copyright © 2020-2023  润新知