基本概念
CS专业的、OI/ACMer不用看
串串香
一些关于字符串的术语 以下术语会用于这篇教程中:
Σ:字母表集合,在这篇教程中为能打在这个帖子中的任何字符,除了 ε ,因为要用它表示空串
字符串:来着 Σ 的0或N个字符的有限序列,也称串
! 在这篇教程中,如果字符串含有空格,会用 "" 包围,否则字符串不含有空格
空串:含有0个字符的字符串,也会用 ε 表示
子串:字符串掐头去尾(0或N个字符)得到的新字符串
> abcbabc 的子串有 abcbabc abcb babc ba ε
> 也就是说在 Java 里,某串A的子串B 可以让 A.contains(B) = true
子序列:字符串随机取出字符(0或N个)得到的新字符串
> abcbabc 的子序列有 abcbabc abab ca ε
真子串:除了自身以外的子串
真子序列:除了自身以外的子序列
一些关于语言的术语 同上,而且这些术语会用的很多:
字符串的连接:两个串的连接为第一个串后紧跟着第二个串的串
假设 A 是字符串 "hailuo " ,B 是字符串 "is " ,C 是字符串 handsome,那么 A B C 的连接表示 ABC,也就是 "hailuo is handsome"
字符串的或:两个串的或为 为第一个串或第二个串的串
假设同上,A C 的或表示为 A|C,也就是 "hailuo " 字符串 或者 handsome 字符串
字符串的Kleene闭包:为0或N个某个串的连接
假设 A 为字符串 ab,A* 为一个启发式寻路算法为 ε ab abab ababababab ....
(字符串):和 字符串 是一样的
字符串操作的优先级 在描述一个字符串时,你可能已经遇到了这类似的问题:
> aac|dbb 是指 {aac,dbb} 还是 {aacbb, aadbb} 呢
> abcd* 是指 {ε, abcd, abcdabcd, ....} 还是 {abc, abcd, abcdddd, ...} 呢
为了解决这些问题,我们可以加括号:
> (aac)|(dbb) 指 {aac,dbb},而 aa(c|d)bb 指 {aacbb, aadbb}
> (abcd)* 指 {ε, abcd, abcdabcd, ....},而 abc((d)*) 指 {abc, abcd, abcdddd, ...}
但是,大量使用括号显然不美观,所以定义以下操作的优先级:
(a) > a* > ab > a|b 也就是说,最上面的两个问题的答案分别为 {aac,dbb} 和 {abc, abcd, abcdddd, ...}
理解以上内容后,你就有足够的基础理解正则表达式了。
为了防止你的理解不够深刻,你可以思考一下以下几个问题:
1. 列出 abcd 的子串、真子串、子序列、真子序列
2. (a|b)* 描述的是什么串
3. a((a|(b*))((b)b|(cc)*)|dd) 可以去掉哪些括号并不影响其表达的字符串
答案1.
子串 {ε, a, b, c, d, ab, bc, cd, abc, bcd, abcd}
真子串 {ε, a, b, c, d, ab, bc, cd, abc, bcd}
子序列 {ε, a, b, c, d, ab, ac, ad, bc, bd, cd, abc, abd, acd, bcd, abcd}
真子序列 {ε, a, b, c, d, ab, ac, ad, bc, bd, cd, abc, abd, acd, bcd}
2. 任意 a b 组成的任意长度的字符串
{ε, a, b, aa, bb, ab, ba, aaa, bbb, aab, aba, babbababbab, ...}
3. a((a|b*)(bb|(cc)*)|dd) |
|
|