String 字符串

String 字符串

KMP

const int maxn = 1e5 + 7;
vector<int> ne(maxn, 0);
string mode, text;
void getNext() {
	int j = 0, k = -1;
	ne = vector<int>(maxn, 0);
	ne[0] = -1;
	while(j < mode.length()) {	
		if(k == -1 || mode[j] == mode[k]) ne[++j] = ++k;
       	else k = ne[k];
	}
}
int KMP_Count() {   // 求匹配次数
	int mode_len = mode.length();
	int text_len = text.length();
	getNext();
	int i = 0, j = 0, ans = 0;
	for(;i < text_len;i++) {
		while(j > 0 && text[i] != mode[j]) j = ne[j];
		if(text[i] == mode[j]) j++;
		if(j == mode_len) {
			ans++;
			j = ne[j];
		}
	}
	return ans;
}
int KMP_Index() {   
	//求第一次匹配到的位置, 当然你也可以find()
	int mode_len = mode.length();
	int text_len = text.length();
	int i = 0, j = 0;
	getNext();
	while(i < text_len && j < mode_len) {
		if(j == -1 || text[i] == mode[j]) i++, j++;	
		else j=ne[j];
	}
	if(j >= mode_len) return i - mode_len;
	else return -1;
}

扩展KMP

Manacher

void Manacher(string ss){
	vector<int > id(1000100, 0);
	int r = 0, mid = 0;
	string s = "$#";
	for(int i = 0;i < ss.length();i++) s += ss[i], s += '#';
	for(int i = 1;i <= s.length();i++) {
		id[i] = r > i ? min(id[2 * mid - i], r - i) : 1;
		while(s[i + id[i]] == s[i - id[i]]) id[i]++;
		if(id[i] > r - i){
			r = id[i] + i;
			mid = i;
		}
	}
    // 对称下标
	int maxId = max_element(id.begin(), id.end()) - id.begin(); 
    // 最长回文串长度
	int maxLen = *max_element(id.begin(), id.end()) - 1;
    // 最长回文串
	string maxPalindrome = "";
	for(int i = maxId - maxLen;i <= maxId + maxLen;i++) if(s[i] != '#') maxPalindrome += s[i];
    return ;
}

Hash

using ll = long long;
//using ull = unsigned __int128;
using ull = unsigned long long;

const ull p = 131;
const int maxn = 1e6 + 7;

string s;

vector<ull> ha(maxn, 0), p_(maxn, 1);

void Hash() {		//string in interval [1, n]
	int n = s.size();
	p_[0] = 1;
	for(int i = 1;i <= n;i++) {
		ha[i] = ha[i - 1] * p + s[i - 1];
		p_[i] = p_[i - 1] * p;
	}
}

ull get(int l, int r) {
	return ha[r] - ha[l - 1] * p_[r - l + 1];
}

字典树

01字典树(求最大异或)

const int maxn = 2e5 + 7;
int tot = 1;

vector<vector<int> > tr(maxn << 5, vector<int>(2, 0));
vector<int> vis(maxn << 5, 0);
	
void insert(int x, int v) {
	int rt = 1;
	for(int i = 30;i >= 0;i--) {
		int now = (x >> i) & 1;
		if(!tr[rt][now]) tr[rt][now] = ++tot;
		rt = tr[rt][now];
		//vis[rt] += v;// mark suffix
	}
	//do mark
	return ;
}

int query(int x) {
	int rt = 1, ret = 0;
	x = ~x;
	for(int i = 30;i >= 0;i--) {
		int now = (x >> i) & 1;
		ret <<= 1;
		if(tr[rt][now] && vis[tr[rt][now]]) {
			ret |= 1;
			rt = tr[rt][now];
		}
		else rt = tr[rt][now ^ 1];
	}
	return ret;
}

AC自动机

后缀数组

后缀自动机

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值