ac自动机:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=550000;
struct AC_auto
{
int chd[maxn][26],v[maxn],f[maxn],last[maxn],sz,ans;
void init()
{
sz=1;
ans=0;
memset(v,0,sizeof(v));
memset(f,0,sizeof(f));
memset(chd[0],0,sizeof(chd[0]));
}
void insert(char* p)
{
int cur=0;
for(; *p; p++)
{
if(!chd[cur][*p-'a'])
{
memset(chd[sz],0,sizeof(chd[sz]));
chd[cur][*p-'a']=sz++;
}
cur=chd[cur][*p-'a'];
}
v[cur]++;
}
bool query(char* p)
{
int cur=0;
for(; *p; p++)
{
if(!chd[cur][*p-'a']) break;
cur=chd[cur][*p-'a'];
}
return v[cur]&&(!(*p));
}
int getFail()
{
queue<int> q;
f[0]=0;
for(int c=0; c<26; c++)
{
int u=chd[0][c];
if(u)
{
f[u]=0;
q.push(u);
last[u]=0;
}
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int c=0; c<26; c++)
{
int u=chd[r][c];
if(!u)
{
chd[r][c]=chd[f[r]][c]; ///....
continue;
}
q.push(u);
int vv=f[r];
while(vv&&!chd[vv][c]) vv=f[vv];
f[u]=chd[vv][c];
last[u]=v[f[u]] ? f[u] : last[f[u]];
}
}
}
void solve(int j)
{
if(!j) return;
if(v[j])
{
ans+=v[j];
v[j]=0;
}
solve(last[j]);
}
void find(char* T)
{
int n=strlen(T),j=0;
getFail();
for(int i=0; i<n; i++)
{
//while(j&&!chd[j][*T-'a']) j=f[j];
j=chd[j][T[i]-'a'];
if(v[j]) solve(j);
else if(last[j]) solve(last[j]);
}
}
} ac;
int main()
{
int t,n;
char dic[100],str[1100000];
scanf("%d",&t);
while(t--)
{
ac.init();
scanf("%d",&n);
while(n--)
{
scanf("%s",dic);
ac.insert(dic);
}
scanf("%s",str);
ac.find(str);
printf("%d\n",ac.ans);
}
return 0;
}
线段树的区间替换和查询:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define max(a,b) (a>b)?a:b
#define min(a,b) (a>b)?b:a
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 100100;
const int INF=0x7fffffff;
using namespace std;
int lazy[maxn<<2];
int MAX[maxn<<2];
int MIN[maxn<<2];
int SUM[maxn<<2];
void PushUp(int rt) { //由左孩子、右孩子向上更新父节点
SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
MAX[rt] = max(MAX[rt<<1],MAX[rt<<1|1]);
MIN[rt] = min(MIN[rt<<1],MIN[rt<<1|1]);
}
void PushDown(int rt,int m) { //向下更新
if (lazy[rt]) { //懒惰标记
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
SUM[rt<<1] = (m - (m >> 1)) * lazy[rt];
SUM[rt<<1|1] = ((m >> 1)) * lazy[rt];
MAX[rt<<1]=MAX[rt<<1|1]=lazy[rt];
MIN[rt<<1]=MIN[rt<<1|1]=lazy[rt];
lazy[rt] = 0;
}
}
//所有的l,r,rt 带入1,n,1
void build(int l,int r,int rt) { //初始化建树
lazy[rt] = 0;
if (l== r) {
SUM[rt]=MAX[rt]=MIN[rt]=0; //初始化为0的建树
/*scanf("%d",&SUM[rt]); //边读入边建树的方法
MAX[rt]=MIN[rt]=SUM[rt];
*/
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int v,int l,int r,int rt) { //将L~R区间的值置为v
//if(L>l||R>r) return;
if (L <= l && r <= R) {
lazy[rt] = v;
SUM[rt] = v * (r - l + 1);
MIN[rt] = v;
MAX[rt] = v;
//printf("%d %d %d %d %d\n", rt, sum[rt], c, l, r);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , v , lson);
if (R > m) update(L , R , v , rson);
PushUp(rt);
}
int querySUM(int L,int R,int l,int r,int rt) { //求区间L~R的和
if (L <= l && r <= R) {
//printf("%d\n", sum[rt]);
return SUM[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
int ret = 0;
if (L <= m) ret += querySUM(L , R , lson);
if (m < R) ret += querySUM(L , R , rson);
return ret;
}
int queryMIN(int L,int R,int l,int r,int rt) { //求区间L~R的最小值
if (L <= l && r <= R) {
//printf("%d\n", sum[rt]);
return MIN[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
int ret = INF;
if (L <= m) ret = min(ret, queryMIN(L , R , lson));
if (m < R) ret = min(ret,queryMIN(L , R , rson));
return ret;
}
int queryMAX(int L,int R,int l,int r,int rt) { //求区间L~R的最大值
if (L <= l && r <= R) {
//printf("%d\n", sum[rt]);
return MAX[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
int ret = -INF;
if (L <= m) ret = max(ret, queryMAX(L , R , lson));
if (m < R) ret = max(ret,queryMAX(L , R , rson));
return ret;
}
int main() {
int n , m;
char str[5];
while(scanf("%d%d",&n,&m)) {
build(1 , n , 1);
while (m--) {
scanf("%s",str);
int a , b , c;
if(str[0]=='T') {
scanf("%d%d%d",&a,&b,&c);
update(a , b , c , 1 , n , 1);
} else if(str[0]=='Q') {
scanf("%d%d",&a,&b);
cout<<querySUM(a,b,1,n,1)<<endl;
} else if(str[0]=='A') {
scanf("%d%d",&a,&b);
cout<<queryMAX(a,b,1,n,1)<<endl;
} else if(str[0]=='I') {
scanf("%d%d",&a,&b);
cout<<queryMIN(a,b,1,n,1)<<endl;
}
}
}
return 0;
}
线段树的区间增加和询问:
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];
void PushUp(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m)
{
if (add[rt])
{
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt] * (m - (m >> 1));
sum[rt<<1|1] += add[rt] * (m >> 1);
add[rt] = 0;
}
}
void build(int l,int r,int rt)
{
add[rt] = 0;
if (l == r)
{
scanf("%lld",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if (L <= l && R>=r)
{
add[rt] += c;
sum[rt] += (LL)c * (r - l + 1);
return ;
}
PushDown(rt, r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L, R, c, lson);
if (m < R) update(L, R, c, rson);
PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
if (L <= l && r <= R)
{
return sum[rt];
}
PushDown(rt, r - l + 1);
int m = (l + r) >> 1;
LL ret = 0;
if (L <= m) ret += query(L, R, lson);
if (m < R) ret += query(L, R, rson);
return ret;
}
int main()
{
int N, Q;
scanf("%d%d",&N,&Q);
build(1, N, 1);
while (Q --)
{
char op[2];
int a, b, c;
scanf("%s",op);
if (op[0] == 'Q')
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(a, b, 1, N, 1));
}
else
{
scanf("%d%d%d",&a,&b,&c);
update(a, b, c, 1, N, 1);
}
}
return 0;
}