BestCoder Round #74 (div.2) LCP Array

本文解析了一个关于字符串的算法问题LCPArray,介绍了如何通过给定的最长公共前缀数组来确定可能的字符串数量,并提供了具体的实现思路及注意事项。

真是TMD,bestcoder 73 竟然做了一天

LCP Array   

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1087    Accepted Submission(s): 306

Problem Description

Peter has a string s=s1s2...sn, let suffi=sisi+1...sn be the suffix start with i-th character of s. Peter knows the lcp (longest common prefix) of each two adjacent suffixes which denotes as ai=lcp(suffi,suffi+1)(1≤i<n).

Given the lcp array, Peter wants to know how many strings containing lowercase English letters only will satisfy the lcp array. The answer may be too large, just print it modulo 109+7.

 

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer n (2≤n≤105) -- the length of the string. The second line contains n−1 integers: a1,a2,...,an−1 (0≤ai≤n).

The sum of values of n in all test cases doesn't exceed 106.

 

Output

For each test case output one integer denoting the answer. The answer must be printed modulo 109+7.

 

Sample Input

3

3

0 0

4

3 2 1

3

1 2

 

Sample Output

16250

26

0







假设对于字符串

a1 a2 a3 a4 a5 a6 a7 a8 a9

第2位的后缀即

a2 a3 a4 a5 a6 a7 a8 a9

和第3位的后缀即

   a3 a4 a5 a6 a7 a8 a9

最长公共前缀长度为3,那么a2=a3,a3=a4,a4=a5;

即a2=a3=a4=a5

规律显而易见

对于字符串

aaafffgggggtre我们写出其给定的数组

2102104321000

观察到

1.如果第i位和第i+1位不同,则arr[i]=0

2.若arr[i]!=0,则第i到i+arr[i]位相同

所以简单起见,可以这样判断:每当读入一个数

1.和上一位比较,如果(差不是1并且上一位不是0) ,则不合法,输出0,结束

2.判断是否为0,如果是0,计数器+1;

最后,通过排列组合知识,

第1位可以选26个字母,以后各位可以选和前一位不同的25个字母,计算答案即可,注意用longlong,边算边模

代码很简单,博主的代码丢了。。。诶呀,linux就是这样,新建很麻烦,所以每次都覆盖了,不过核心代码只有不过10行,大家自己写吧!

为了给抄代码的同学提供方便,大家可以去我同学DERIT的博客抄   http://blog.youkuaiyun.com/deritt/article/details/50822077

祝大家母亲节快乐





​ 前言 JavaScript作为现代Web应用的核心技术,其性能直接影响用户体验。随着应用复杂度增加,性能优化成为开发者必须掌握的技能。本文将从多个维度深入探讨JavaScript性能优化的实战策略和技巧。 一、代码层面优化 1.1 减少DOM操作 DOM操作是JavaScript中最耗性能的操作之一,应尽量减少DOM访问和修改次数。 实战技巧: // 不佳实践:频繁操作DOM for (let i = 0; i < 1000; i++) { document.getElementById(&#39;list&#39;).innerHTML += `<li>Item ${i}</li>`; } // 优化实践:使用文档片段批量操作 const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const li = document.createElement(&#39;li&#39;); li.textContent = `Item ${i}`; fragment.appendChild(li); } document.getElementById(&#39;list&#39;).appendChild(fragment); 1.2 事件委托 利用事件冒泡机制,减少事件处理器的数量。 // 不佳实践:为每个元素绑定事件 document.querySelectorAll(&#39;.item&#39;).forEach(item => { item.addEventListener(&#39;click&#39;, handleClick); }); // 优化实践:事件委托 document.getElementById(&#39;container&#39;).addEventListener(&#39;click&#39;, (e) => { if (e.target.classList.contains(&#39;item&#39;)) { handleClick(e); } }); 1.3 避免不必要的计算 缓存重复使用的计算结果和DOM查询。 // 不佳实践:重复计算和查询 function calculateWidth() { const element = document.getElementById(&#39;content&#39;); return element.offsetWidth * 0.8; } // 优化实践:缓存结果 let cachedWidth = null; function calculateWidth() { if (cachedWidth === null) { const element = document.getElementById(&#39;content&#39;); cachedWidth = element.offsetWidth * 0.8; } return cachedWidth; } 1.4 使用Web Worker处理密集型任务 将CPU密集型任务转移到Web Worker,避免阻塞主线程。 // 主线程代码 const worker = new Worker(&#39;task.js&#39;); worker.postMessage({ data: largeData }); worker.onmessage = (e) => { console.log(&#39;Result:&#39;, e.data); }; // task.js self.onmessage = (e) => { const result = processLargeData(e.data); self.postMessage(result); }; 二、内存管理优化 2.1 避免内存泄漏 常见内存泄漏场景及解决方案: // 1. 意外的全局变量 function leak() { leakedVar = &#39;这是一个全局变量&#39;; // 未使用var/let/const } // 2. 被遗忘的定时器 const intervalId = setInterval(() => { // 操作... }, 1000); // 需要时清除:clearInterval(intervalId); // 3. DOM引用 const elements = { button: document.getElementById(&#39;button&#39;) }; // 即使从DOM移除,elements.button仍保留引用 2.2 合理使用对象池 对于频繁创建和销毁的对象,使用对象池技术。 class ObjectPool { constructor(createFn) { this.createFn = createFn; this.pool = []; } get() { return this.pool.length > 0 ? this.pool.pop() : this.createFn(); } release(obj) { this.pool.push(obj); } } // 使用示例 const particlePool = new ObjectPool(() => ({ x: 0, y: 0, vx: 0, vy: 0, active: false })); 三、网络性能优化 3.1 代码拆分与懒加载 使用动态import实现按需加载。 // 静态导入 // import { heavyModule } from &#39;./heavy-module&#39;; // 动态导入(懒加载) button.addEventListener(&#39;click&#39;, async () => { const { heavyModule } = await import(&#39;./heavy-module&#39;); heavyModule.doWork(); }); 3.2 资源预加载 使用<link rel="preload">或Resource Hints。 <!-- 预加载关键资源 --> <link rel="preload" href="critical.js" as="script"> <link rel="preload" href="important.css" as="style"> 四、渲染性能优化 4.1 减少重绘和回流 优化策略: // 不佳实践:多次修改样式引起多次回流 element.style.width = &#39;100px&#39;; element.style.height = &#39;200px&#39;; element.style.margin = &#39;10px&#39;; // 优化实践1:使用cssText批量修改 element.style.cssText = &#39;width: 100px; height: 200px; margin: 10px;&#39;; // 优化实践2:使用classList element.classList.add(&#39;new-style&#39;); // 优化实践3:离线DOM操作 const container = document.getElementById(&#39;container&#39;); container.style.display = &#39;none&#39;; // 批量DOM操作... container.style.display = &#39;block&#39;; 4.2 使用requestAnimationFrame 优化动画性能,确保与浏览器刷新率同步。 function animate() { // 动画逻辑 requestAnimationFrame(animate); } requestAnimationFrame(animate); 4.3 使用WebGL进行复杂图形处理 对于数据可视化、游戏等高性能图形需求,考虑使用WebGL。 五、算法与数据结构优化 5.1 选择合适的数据结构 根据场景选择最优数据结构。 // 需要快速查找时使用Set/Map const largeSet = new Set(largeArray); console.log(largeSet.has(&#39;target&#39;)); // O(1)时间复杂度 // 需要有序数据时使用数组 const sortedArray = [...largeSet].sort(); 5.2 优化循环性能 // 不佳实践:在循环中执行昂贵操作 for (let i = 0; i < array.length; i++) { expensiveOperation(array[i]); } // 优化实践1:缓存长度 for (let i = 0, len = array.length; i < len; i++) { expensiveOperation(array[i]); } // 优化实践2:使用更快的循环方法 array.forEach(item => { expensiveOperation(item); }); 六、工具与监控 6.1 性能分析工具 6.2 实时性能监控 // 监控长任务 const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.duration > 50) { console.warn(&#39;长任务 detected:&#39;, entry); } } }); observer.observe({ entryTypes: [&#39;longtask&#39;] }); // 监控FPS let frameCount = 0; let lastTime = performance.now(); function checkFPS() { frameCount++; const currentTime = performance.now(); if (currentTime - lastTime >= 1000) { const fps = Math.round((frameCount * 1000) / (currentTime - lastTime)); if (fps < 30) { console.warn(&#39;低FPS:&#39;, fps); } frameCount = 0; lastTime = currentTime; } requestAnimationFrame(checkFPS); } checkFPS(); 七、框架特定优化 7.1 React优化实践 // 使用React.memo避免不必要的重渲染 const ExpensiveComponent = React.memo(({ data }) => { // 组件逻辑 }); // 使用useCallback和useMemo缓存值和函数 const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]); const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); 7.2 Vue优化实践 // 使用v-once和v-memo <template> <div v-memo="[value]"> {{ value }} </div> </template> // 合理使用计算属性 computed: { optimizedData() { // 只有依赖变化时才重新计算 return this.heavyComputation(this.sourceData); } } 总结 JavaScript性能优化是一个持续的过程,需要开发者从多个维度综合考虑。关键点包括: 性能优化不是一蹴而就的,应该在开发过程中持续关注,并通过测试确保优化效果。记住,最好的优化往往是那些不需要复杂技巧的简单改进——比如删除不必要的代码或选择更高效的算法。 延伸阅读 通过实践这些优化技巧,您可以显著提升JavaScript应用的性能,为用户提供更流畅的体验。 ​生成思维导图
最新发布
09-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值