博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #337 Alphabet Permutations
阅读量:7070 次
发布时间:2019-06-28

本文共 5532 字,大约阅读时间需要 18 分钟。

E. Alphabet Permutations
time limit per test: 
1 second
memory limit per test: 
512 megabytes
input: 
standard input
output: standard output

You are given a string s of length n, consisting of first k lowercase English letters.

We define a c-repeat of some string q as a string, consisting of c copies of the string q. For example, string "acbacbacbacb" is a 4-repeat of the string "acb".

Let's say that string a contains string b as a subsequence, if string b can be obtained from a by erasing some symbols.

Let p be a string that represents some permutation of the first k lowercase English letters. We define function d(p) as the smallest integer such that a d(p)-repeat of the string p contains string s as a subsequence.

There are m operations of one of two types that can be applied to string s:

  1. Replace all characters at positions from li to ri by a character ci.
  2. For the given p, that is a permutation of first k lowercase English letters, find the value of function d(p).

All operations are performed sequentially, in the order they appear in the input. Your task is to determine the values of function d(p) for all operations of the second type.

Input

The first line contains three positive integers nm and k (1 ≤ n ≤ 200 000, 1 ≤ m ≤ 20000, 1 ≤ k ≤ 10) — the length of the string s, the number of operations and the size of the alphabet respectively. The second line contains the string s itself.

Each of the following lines m contains a description of some operation:

  1. Operation of the first type starts with 1 followed by a triple liri and ci, that denotes replacement of all characters at positions from lito ri by character ci (1 ≤ li ≤ ri ≤ nci is one of the first k lowercase English letters).
  2. Operation of the second type starts with 2 followed by a permutation of the first k lowercase English letters.
Output

For each query of the second type the value of function d(p).

Sample test(s)
input
7 4 3 abacaba 1 3 5 b 2 abc 1 4 4 c 2 cba
output
6 5
Note

After the first operation the string s will be abbbbba.

In the second operation the answer is 6-repeat of abc: ABcaBcaBcaBcaBcAbc.

After the third operation the string s will be abbcbba.

In the fourth operation the answer is 5-repeat of cba: cbAcBacBaCBacBA.

Uppercase letters means the occurrences of symbols from the string s.

 

 

思路:容易证明答案等于1+字符串中相邻字符对不可成为置换串(模式串)子串的对数。

本题关键是如何充分利用题目信息降低计算复杂度。由于操作1和操作2有2e4次,显然不能每次遍历文本串。

注意到串是定长的,因此字符对数固定,而字符相邻关系可以用k * k矩阵表示。

 考虑问题的反面,只需计数文本串中所有相邻字符对满足可成为模式串子串的对数。

k*k矩阵记录当前串中字符i与字符j相邻的相邻字符对对数。这样记录的目的是为了应对模式串的改变。

用线段树储存字符串子串相邻字符对出现次数的信息,这样同时标记端点字符即可进行子串的合并。

 

代码:

 

 

1 #include 
2 #include
3 #include
4 #define lson (u << 1) 5 #define rson (u << 1 | 1) 6 using namespace std; 7 const int maxn = 2e5 + 10; 8 char T[maxn], P[20]; 9 int n, m, k;10 struct Seg{11 int l, r;12 char left, right;13 int lazy;14 int mt[11][11];15 }seg[maxn << 2];16 17 void push_up(int u){18 memset(seg[u].mt, 0, sizeof seg[u].mt);19 for(int i = 0; i < k; i++) for(int j = 0; j < k; j++) seg[u].mt[i][j] += seg[lson].mt[i][j] + seg[rson].mt[i][j];20 seg[u].left = seg[lson].left, seg[u].right = seg[rson].right;21 seg[u].mt[seg[lson].right - 'a'][seg[rson].left - 'a']++;22 }23 24 void build(int u, int l, int r){25 seg[u].l = l, seg[u].r = r;26 seg[u].left = T[l], seg[u].right = T[r - 1];27 seg[u].lazy = 0;28 memset(seg[u].mt, 0, sizeof seg[u].mt);29 if(r - l < 2) return;30 int mid = (l + r) >> 1;31 build(lson, l, mid), build(rson, mid, r);32 push_up(u);33 }34 35 void push_down(int u){36 if(!seg[u].lazy) return;37 memset(seg[lson].mt, 0, sizeof seg[lson].mt);38 memset(seg[rson].mt, 0, sizeof seg[rson].mt);39 seg[lson].mt[seg[u].left - 'a'][seg[u].left - 'a'] = seg[lson].r - seg[lson].l - 1;40 seg[rson].mt[seg[u].left - 'a'][seg[u].left - 'a'] = seg[rson].r - seg[rson].l - 1;41 seg[u].lazy = 0;42 seg[lson].lazy = seg[rson].lazy = 1;43 seg[lson].left = seg[rson].left = seg[lson].right = seg[rson].right = seg[u].left;44 }45 46 void cover(int u, int l, int r, int L, int R, char ch){47 if(l == L && r == R){48 memset(seg[u].mt, 0, sizeof seg[u].mt);49 seg[u].left = seg[u].right = ch;50 seg[u].lazy = 1;51 seg[u].mt[ch - 'a'][ch - 'a'] = r - l - 1;52 return;53 }54 push_down(u);55 int mid = (l + r) >> 1;56 if(R <= mid) cover(lson, l, mid, L, R, ch);57 else if(L >= mid) cover(rson, mid, r, L, R, ch);58 else{59 cover(lson, l, mid, L, mid, ch);60 cover(rson, mid, r, mid, R, ch);61 }62 push_up(u);63 }64 65 int getAns(){66 int ans = 0;67 for(int i = 0; i < k; i++) for(int j = i + 1; j < k; j++){68 ans += seg[1].mt[P[i] - 'a'][P[j] - 'a'];69 }70 ans = n - ans;71 return ans;72 }73 74 int main(){75 //freopen("in.txt", "r", stdin);76 while(~scanf("%d%d%d", &n, &m, &k)){77 scanf("%s", T + 1);78 build(1, 1, n + 1);79 char ch;80 for(int i = 0, op, l, r; i < m; i++){81 scanf("%d", &op);82 if(op == 1){83 scanf("%d%d %c", &l, &r, &ch);84 cover(1, 1, n + 1, l, r + 1, ch);85 }else{86 scanf("%s", P);87 int ans = getAns();88 printf("%d\n", ans);89 }90 }91 }92 return 0;93 }
View Code

 

转载于:https://www.cnblogs.com/astoninfer/p/5103606.html

你可能感兴趣的文章
Python进阶07 函数对象
查看>>
使用ASP.Net WebAPI构建REST服务(五)——客户端
查看>>
C语言双向链表
查看>>
Memcached在Windows下的配置和使用(转)
查看>>
中国国际服装服饰博览会 _百度百科
查看>>
设置tableView背景颜色
查看>>
c# 中的UserControl是什么 用户控件和自定义控件有什么区别
查看>>
漂亮的ActionBar效果
查看>>
32 脚本编程风格
查看>>
让低版本的 Android 项目显示出 Material 风格的点击效果
查看>>
来一篇新鲜的招聘笔试题(2014秋招版)
查看>>
HashMap工作原理(转载)
查看>>
hive0.13.1配置hwi
查看>>
CSS3 Filter的十种特效
查看>>
实用的eclipse adt 快捷键
查看>>
bootstrap 树
查看>>
Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明
查看>>
电容知识汇总
查看>>
【转】模块编译Android源码方法
查看>>
iOS8 CIGlassDistortion滤镜的使用
查看>>