自备ACM模板 —— 字符串篇

Shift-And/Shift-Or

Shift-And

        b i t s e t bitset bitset 初始长度为文本串长度, p o s pos pos 初始化为各个字符出现的位置( b i t s e t bitset bitset 中位置关系是倒置的,0 在最后面)。

        a n s = ( a n s < < 1 ∣ 1 )   &   p o s [ s [ i ] ] ans=(ans<<1\mid1)\ \&\ pos[s[i]] ans=(ans<<11) & pos[s[i]] s [ i ] s[i] s[i] 表示对应位置字符。

       最后判断 a n s [ n − 1 ] ans[n-1] ans[n1] 即可知道答案。

// hdu 5972
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
typedef long long LL;
using PII = pair<int, int>;
const int maxn = 5e6 + 5;
const int mod = 1e9 + 7;

bitset<5> pos[10], ans;
char s[maxn];

int main(){
   
    IOS;
    int n, k, v;
    while(cin >> n){
   
        for(int i = 0; i <= 9; i++) pos[i].reset();
        for(int i = 0; i < n; i++){
   
            cin >> k;
            while(k--){
   
                cin >> v;
                pos[v].set(i);
            }
        }
        cin >> s;
        ans.reset();
        for(int i = 0; s[i]; i++){
   
            ans <<= 1;
            ans |= 1; // ans.set(0);
            ans &= pos[s[i] - '0'];
            cout << s[i] << "   " << ans << endl;
            if(ans[n - 1]){
   
                char now = s[i + 1];
                s[i + 1] = '\0';
                cout << (s + i - n + 1) << endl;
                s[i + 1] = now;
            }
        }
    }
}

Shift-Or

        b i t s e t bitset bitset 初始长度为文本串长度, p o s pos pos 初始化为各个字符出现的位置。(和 S h i f t − A n d Shift-And ShiftAnd 不同,0 表示出现,1 表示未出现)

        a n s = ( a n s < < 1 ) ∣ p o s [ s [ i ] ] ans=(ans<<1)\mid pos[s[i]] ans=(ans<<1)pos[s[i]] s [ i ] s[i] s[i] 表示对应位置字符。

       最后判断 ! a n s [ n − 1 ] !ans[n-1] !ans[n1] 即可知道答案。比 S h i f t − A n d Shift-And ShiftAnd 少了一步操作,效率略有提升。

// hdu 5972
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
typedef long long LL;
using PII = pair<int, int>;
const int maxn = 5e6 + 5;
const int mod = 1e9 + 7;

bitset<1005> pos[10], ans;
char s[maxn];

int main(){
   
    IOS;
    int n, k, v;
    while(cin >> n){
   
        for(int i = 0; i <= 9; i++) pos[i].set();
        for(int i = 0; i < n; i++){
   
            cin >> k;
            while(k--){
   
                cin >> v;
                pos[v].reset(i);
            }
        }
        cin >> s;
        ans.set();
        for(int i = 0; s[i]; i++){
   
            ans <<= 1;
            ans |= pos[s[i] - '0'];
            if(!ans[n - 1]){
   
                char now = s[i + 1];
                s[i + 1] = '\0';
                cout << (s + i - n + 1) << endl;
                s[i + 1] = now;
            }
        }
    }
}

KMP

        n e x t [ i ] next[i] next[i] 表示 S S S 子串 S [ 0 , i ] S[0,i] S[0,i] 的真后缀与真前缀的最大公共前缀长度,同时也是该位置失配后跳转的位置。

        n e x t [ i ] next[i] next[i] 表示长度为 i i i 的前缀的最长 b o r d e r border border 长度

       匹配过程中, S S S 串一直在往后移动

        S S S A B A ABA ABA T T T A B A B A ABABA ABABA,匹配过程如下:

        A B A B A ABABA ABABA
        A B A ABA ABA

        A B A B A ABABA ABABA
               A B A \ \ \ \ \ \ ABA       ABA

//打印 s2 串在 s1 串的位置	洛谷 P3375
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 5;

char s1[maxn], s2[maxn];
int nxt[maxn], len1, len2;

inline void getnext(){
   
    nxt[0] = nxt[1] = 0;
    for(int i = 1, j; i < len2; i++){
   
        j = nxt[i];
        while(j && s2[i] != s2[j]) j = nxt[j];
        nxt[i + 1] = (s2[i] == s2[j] ? j + 1 : 0);
    }
}

int main(){
   
    IOS;
    cin >> s1 >> s2;
    len1 = strlen(s1), len2 = strlen(s2);
    getnext();
    for(int i = 0, j = 0; i < len1; i++){
   
        while(j && s1[i] != s2[j]) j = nxt[j];
        if(s1[i] == s2[j]) j++;
        if(j == len2){
   
            cout << i - len2 + 2 << endl;
            j = nxt[j];
        }
    }
    for(int i = 1; i <= len2; i++) cout << nxt[i] << " ";
}

扩展KMP

        e x [ i ] ex[i] ex[i] 数组表示字符串的后缀 S [ i , n − 1 ] S[i,n-1] S[i,n1] 和字符串 s s s 的最大公共前缀长度,将要查询的串和 s s s 串并在一起即可同时求出 e x ex ex 数组。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
typedef long long LL;
const int maxn = 4e7 + 5;
const LL mod = 998244353;
int ex[maxn], slen, tlen;
char s[maxn], t[maxn];
inline void getex(){
   
    int n = slen;
    for(int i = 1, l = 0, r = 0; i < n; i++){
   
        ex[i] = i <= r ? min(r - i + 1, ex[i - l]) : 0;
        while(i + ex[i] < n && s[ex[i]] == s[i + ex[i]]) ex[i]++;
        if(i + ex[i] - 1 > r) l = i, r = i + ex[i] - 1;
    }
}

int main(){
   
    IOS;
    cin >> t >> s;
    slen = strlen(s), tlen = strlen(t);
    s[slen] = '|';
    ex[0] <
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
看大小就知道很全啦 查看地址 https://blog.csdn.net/qq_43333395/article/details/98508424 目录: 数据结构: 1.RMQ (区间最值,区间出现最大次数,求区间gcd) 2.二维RMQ求区间最大值 (二维区间极值) 3.线段树模板(模板为区间加法) (线段树染色) (区间最小值) 4.线性基 (求异或第k大) 5.主席树(静态求区间第k小) (区间中小于k的数量和小于k的总和) (区间中第一个大于或等于k的值) 6.权值线段树 (求逆序对) 7.动态主席树 (主席树+树状数组) (区间第k大带修改) 8.树上启发式合并 (查询子树的优化) 9,树状数组模板 (求区间异或和,求逆序对) 扩展 10.区间不重复数字的和 (树状数组) 11.求k维空间中离所给点最近的m个点,并按顺序输出(KD树) 12.LCA (两个节点的公共父节点) 动态规划: 1.LIS (最长上升子序列) 2.有依赖的背包 (附属关系) 3.最长公共子序列(LCS) 4.树形DP 5.状压DP-斯坦纳树 6.背包 7.dp[i]=min(dp[i+1]…dp[i+k]),multset 博弈: 1.NIM博弈 (n堆每次最少取一个) 2.威佐夫博弈(两堆每次取至少一个或一起取一样的) 3.约瑟夫环 4.斐波那契博弈 (取的数依赖于对手刚才取的数) 5.sg函数 数论: 1.数论 素数检验:普通素数判别 线性筛 二次筛法求素数 米勒拉宾素数检验 2.拉格朗日乘子法(求有等式约束条件的极值) 3.裂项(多项式分子分母拆分) 4.扩展欧几里得 (ax+by=c) 5.勾股数 (直角三角形三边长) 6.斯特林公式 (n越大越准确,求n!) 7.牛顿迭代法 (求一元多次方程一个解) 8.同余定理 (a≡b(mod m)) 9.线性求所有逆元的方法求 (1~p modp的逆元) 10.中国剩余定理(n个同余方程x≡a1(modp1)) 11.二次剩余((ax+k)2≡n(modp)(ax+k)^2≡n(mod p)(ax+k) 2 ≡n(modp)) 12.十进制矩阵快速幂(n很大很大的时候) 13.欧拉函数 14.费马小定理 15.二阶常系数递推关系求解方法 (a_n=p*a_{n-1}+q*a_{n-2}) 16.高斯消元 17.矩阵快速幂 18.分解质因数 19.线性递推式BM(杜教) 20.线性一次方程组解的情况 21.求解行列式的逆矩阵,伴随矩阵,矩阵不全随机数不全 组合数学: 1.循环排列 (与环有关的排列组合) 计算几何: 1.三角形 (求面积)) 2.多边形 3.三点求圆心和半径 4.扫描线 (矩形覆盖求面积) (矩形覆盖求周长) 5.凸包 (平面上最远点对) 6.求凸多边形的直径 7.求凸多边形的宽度 8.求凸多边形的最小面积外接矩形 9.半平面交 图论: 基础:前向星 1.最短路(优先队列dijkstra) 2.判断环(tarjan算法) 3.最小生成树(Kruskal 模板) 4.最小生成树(Prim) 5.Dicnic最大流(最小割) 6.无向图最小环(floyd) 7.floyd算法的动态规划(通过部分指定边的最短路) 8.图中找出两点间的最长距离 9.最短路 (spfa) 10.第k短路 (spfa+A*) 11.回文树模板 12.拓扑排序 (模板) 13.次小生成树 14.最小树形图(有向最小生成树) 15.并查集 (普通并查集,带权并查集,) 16.求两个节点的最近公共祖先 (LCA) 17.限制顶点度数的MST(k度限制生成树) 18.多源最短路(spfa,floyd) 19.最短路 (输出字典序最小) 20.最长路 图论题目简述 字符串: 1.字典树(多个字符串的前缀) 2.KMP(关键字搜索) 3.EXKMP(找到S中所有P的匹配) 4.马拉车(最长回文串) 5.寻找两个字符串的最长前后缀(KMP) 6.hash(进制hash,无错hash,多重hash,双hash) 7.后缀数组 (按字典序排字符串后缀) 8.前缀循环节(KMP的fail函数) 9.AC自动机 (n个kmp) 10.后缀自动机 小技巧: 1.关于int,double强转为string 2.输入输出挂 3.低精度加减乘除 4.一些组合数学公式 5.二维坐标的离散化 6.消除向下取整的方法 7.一些常用的数据结构 (STL) 8.Devc++的使用技巧 9.封装好的一维离散化 10.Ubuntu对拍程序 11.常数 12.Codeblocks使用技巧 13.java大数 叮嘱 共173页

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值