/*正则表达式的模式匹配:
生成有向图的思路,(和|放进符号栈,遇到)从符号栈取符号,取到|后继续取(,需要加两条有向边,具体看代码;取到(的修改做索引,为当前循环里可能进行的*判断做准备。
对当前索引+1进行*判断,当前字符不是)则与当前索引创建两条边,如果是)则与栈里上一个(的索引创建两条边。
最后当前是()*的情况创建一条边到下一个索引,因为运算顺序是从左到右,|不加是因为|应该与右括号连接。
其他字符(如a,1)都不用加取下一个索引的边,识别的时候才加。否则只要txt最后一个字符在re里就能匹配。
*/
//用正则表达式文本生成有向图
function getGraph(re){
let M=re.length
let graph=[] //用二维数组表示图
for(let i=0;i<=M;i++){graph[i]=[]}
let ops=[] //符号栈
for(let i=0;i<M;i++){
let c=re[i]
let left=i //左索引
if(c=='('||c=='|'){
ops.push(i)
}else if(c==')'){
let or=ops.pop() //中索引
if(re[or]=='|'){
left=ops.pop()
graph[or].push(i)
graph[left].push(or+1)
}else if(re[or]=='('){
left=or //left给*做判断用的,只有*需要查看未来,索引是i+1
}
}
if(i<M-1&&re[i+1]=='*'){ //i<M-1单纯为了防止越界
graph[i+1].push(left)
graph[left].push(i+1)
}
if(c=='('||c==')'||c=='*'){graph[i].push(i+1)}
}
console.log(JSON.stringify(graph))
return graph
}
//在有向图graph里查找s能到达的所有点,放在list里返回
function dfs(graph,s,list=[]){
list.push(s)
for(let i in graph[s]){
let c=graph[s][i]
if(list.indexOf(c)==-1){
//list.push(c) //释放此行并注释list.push(s)会丢失第一个s
list=dfs(graph,c,list)
}
}
return Array.from(new Set(list))
}
//判断re能否匹配txt
function recognizes(txt,re){
let graph=getGraph(re)
var pc=dfs(graph,0)
//console.log('start::::',JSON.stringify(pc))
for(let t=0;t<txt.length;t++){
let newpc=[]
for(let i in pc){
let v=pc[i]
if(re[v]==txt[t]||re[v]=='.'){
newpc=dfs(graph,v+1)
//console.log('newpc:::',JSON.stringify(newpc),v+1)
}
}
pc=newpc
//console.log(t,JSON.stringify(pc))
}
for(let i in pc){
if(pc[i]==re.length){return true}
}
return false
}
var re='(.*ab*((c|d*e)f)*g)'
var re1='((1|2)|8)' //'(1|2|8)'拿不到正确的值
//let G=getGraph(re)
//let pc=dfs(G,3)
console.log(recognizes('bacfefdeg',re)) //false
console.log(recognizes('bacfefdefg',re)) //true
console.log(recognizes('bacfefdeffg',re)) //false
console.log(recognizes('1',re1)) //true
console.log(recognizes('2',re1)) //true
console.log(recognizes('8',re1)) //true
js版本正则表达式的模式匹配
最新推荐文章于 2024-01-12 10:38:55 发布