题目链接:树状数组 trie树 AC自动机
A:
思路:kmp直接进行匹配
#include <iostream>
using namespace std;
char S[1000100];
char T[10100];
int nextval[10100];
int n, m;
void get_next()
{
int i = 1, j = 0;
nextval[1] = 0;
while (i <= m)
{
if (j == 0 || T[i] == T[j])
{
++i, ++j;
nextval[i] = j;
}
else j = nextval[j];
}
}
void kmp()
{
int i = 1, j = 1, cnt = 0;
while (i <= n && j <= m)
{
if (j == 0 || S[i] == T[j]) i++, j++;
else j = nextval[j];
if (j > m)
{
cnt++;
j = nextval[j];
}
}
printf("%d\n", cnt);
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%s", &T[1]);
scanf("%s", &S[1]);
n = strlen(S + 1);
m = strlen(T + 1);
get_next();
kmp();
}
}
B:
思路:后序遍历+树状数组
#include <iostream>
#include <queue>
#include <string>
#include <string.h>
const int maxn = 100010;
using namespace std;
int n;
struct node
{
int v, next;
}e[maxn<<1];
int head[maxn];
int cnt = 0;
int time = 0;
int c[maxn];
int a[maxn];
bool vis[maxn];
struct point
{
int stime, etime;
}p[maxn];
void add(int u, int v)
{
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int u)
{
p[u].stime = ++time;
vis[u] = true;
for (int i = head[u]; i; i = e[i].next)
{
if (vis[e[i].v]) continue;
dfs(e[i].v);
}
p[u].etime = time;
}
int lowbit(int x)
{
return x & (-x);
}
void update(int x,int k)
{
while (x <= n)
{
c[x] += k;
x += lowbit(x);
}
}
int getsum(int x)
{
int ans = 0;
while (x >= 1)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
a[i] = 1;
update(i, 1);
}
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
dfs(1);
//for (int i = 1; i <= n; i++) cout << p[i].stime << " " << p[i].etime << endl;
int m;
scanf("%d", &m);
while (m--)
{
char op;
int x;
scanf(" %c%d", &op, &x);
if (op == 'Q')
{
printf("%d\n", getsum(p[x].etime) - getsum(p[x].stime - 1));
}
else
{
if (a[x]) {
a[x] = 0;
update(p[x].stime, -1);
}
else {
a[x] = 1;
update(p[x].stime, 1);
}
}
}
}
C:
思路:
有交点→(x2-x1)*(y2-y1)< 0
以x为下标 求y的逆序对即可
暴力求逆序对会T掉,需要用线段树或者树状数组
这里给出树状数组解法
#include <iostream>
#include <queue>
#include <string>
#include <string.h>
const int maxn = 1010;
#define ll long long
using namespace std;
int n, m, k;
queue <int> q;
struct node
{
int x, y;
}line[maxn*maxn];
bool cmp(node& n1, node& n2)
{
if(n1.x==n2.x)
return n1.y < n2.y;
return n1.x < n2.x;
}
int c[maxn];
int lowbit(int x)
{
return x & (-x);
}
void update(int x,int k)
{
while (x <= m)
{
c[x] += k;
x += lowbit(x);
}
}
int getsum(int x)
{
int ans = 0;
while (x >= 1)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
int kase = 0;
while (t--)
{
while (q.size()) q.pop();
memset(c, 0, sizeof(c));
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= k; i++)
{
scanf("%d%d", &line[i].x, &line[i].y);
}
sort(line + 1, line + 1 + k, cmp);
ll ans = 0;
for (int i = 1,j=1; i <= k;i++)
{
ans += j - 1 - getsum(line[i].y);
//cout << ans << endl;
//cout <<i<<":"<< getsum(line[i].y+1) << endl;
if (line[i + 1].x > line[i].x)
{
j += q.size()+1;
while (q.size())
{
int tmp = q.front();
update(tmp, 1);
//cout << "update:" << tmp << endl;
q.pop();
}
update(line[i].y, 1);
//cout << "update2:" << line[i].y << endl;
}
else //如果下一个的x不比这一个大,延缓此次update
q.push(line[i].y);
}
//cout << getsum(4) << endl;
printf("Test case %d: %lld\n", ++kase, ans);
}
}
D:
思路:字典树插入与查找
#include <iostream>
#include <queue>
#include <string>
#include <string.h>
const int maxn = 1010;
#define ll long long
using namespace std;
const int maxnode = 1010000;
const int maxchar = 26;
int tried[maxnode][maxchar];
char a[maxnode][maxchar];
int color[maxnode];
char s[25];
int cnt = 0;
void insert(char* s)
{
int len = strlen(s);
int p = 0;
color[p]++;
for (int i = 0; i < len; i++)
{
int c = s[i] - 'a';
if (!tried[p][c])
{
tried[p][c] = ++cnt;
color[cnt]++;
p = cnt;
}
else
{
p = tried[p][c];
color[p]++;
}
}
}
void search(char* s) {
int len = strlen(s);
int p = 0;
for (int i = 0; i < len; i++) {
int c = s[i] - 'a';
p = tried[p][c];
printf("%c", s[i]);
if (color[p]==1) return;
}
}
int main()
{
int tot = 0;
while (scanf("%s",a[++tot])!=EOF)
{
insert(a[tot]);
}
for (int i = 1; i <= tot; i++)
{
printf("%s ", a[i]);
search(a[i]);
printf("\n");
}
}
F:
思路:AC自动机模板
#include<iostream>
#include<algorithm>
#include<string.h>
#include <queue>
using namespace std;
const int maxn = 1000001;
char s[maxn];
int n, cnt;
queue <int> q;
struct node
{
int son[26], flag, fail;
}trie[maxn];
void insert(char* s)
{
int u = 1, len = strlen(s);
for (int i = 0; i < len; i++)
{
int v = s[i] - 'a';
if(!trie[u].son[v]) trie[u].son[v] = ++cnt;
u = trie[u].son[v];
}
trie[u].flag++;
}
void getfail()
{
for (int i = 0; i < 26; i++) trie[0].son[i] = 1;
q.push(1);
trie[1].fail = 0;
while (q.size())
{
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++)
{
int v = trie[u].son[i];
int Fail = trie[u].fail;
if (!v) { trie[u].son[i] = trie[Fail].son[i]; continue; }
trie[v].fail = trie[Fail].son[i];
q.push(v);
}
}
}
int query(char* s)
{
int u = 1, ans = 0, len = strlen(s);
for (int i = 0; i < len; i++)
{
int v = s[i] - 'a';
int k = trie[u].son[v];
while (k > 1 && trie[k].flag != -1)
{
ans += trie[k].flag;
trie[k].flag = -1;
k = trie[k].fail;
}
u = trie[u].son[v];
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
cnt = 1;
memset(trie, 0, sizeof(trie));
scanf("%d", &n);
while (n--)
{
scanf("%s", &s);
insert(s);
}
getfail();
scanf("%s", &s);
printf("%d\n", query(s));
}
}